From: gumartinm Date: Wed, 21 Mar 2012 07:10:35 +0000 (+0100) Subject: Android MobiAds appliction working. X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=74df4571900aefb6f8c032b26824237a5aed2d7b;p=JavaForFun Android MobiAds appliction working. Just is left to fix some issues about closing the sqlite database. --- diff --git a/Android/MobiAds/gen/de/android/mobiads/R.java b/Android/MobiAds/gen/de/android/mobiads/R.java index 417c50b..93833a5 100644 --- a/Android/MobiAds/gen/de/android/mobiads/R.java +++ b/Android/MobiAds/gen/de/android/mobiads/R.java @@ -37,7 +37,7 @@ public final class R { public static final int button_messagestopservice=0x7f04000b; public static final int button_messageunbind=0x7f04000a; public static final int button_ok=0x7f04000d; - public static final int encoded_web_service=0x7f040014; + public static final int encoded_web_service=0x7f040015; public static final int error_dialog_connection_error=0x7f040004; public static final int error_dialog_userpwd_error=0x7f040005; public static final int hello=0x7f040000; @@ -46,7 +46,8 @@ public final class R { public static final int remote_service_started=0x7f04000f; public static final int remote_service_stopped=0x7f040010; public static final int url_login_web_service=0x7f040012; - public static final int user_agent_web_service=0x7f040013; + public static final int url_web=0x7f040013; + public static final int user_agent_web_service=0x7f040014; public static final int username=0x7f040006; } } diff --git a/Android/MobiAds/res/values/strings.xml b/Android/MobiAds/res/values/strings.xml index 653249f..eb386ef 100644 --- a/Android/MobiAds/res/values/strings.xml +++ b/Android/MobiAds/res/values/strings.xml @@ -20,6 +20,7 @@ MobiAds Service Stopped MobiAds Service http://users.mobiads.gumartinm.name/userfront.php/api/login/auth.json + users.mobiads.gumartinm.name MobieAds/1.0 UTF-8 diff --git a/Android/MobiAds/src/de/android/mobiads/MobiAdsLoginActivity.java b/Android/MobiAds/src/de/android/mobiads/MobiAdsLoginActivity.java index 01435fe..cde859a 100644 --- a/Android/MobiAds/src/de/android/mobiads/MobiAdsLoginActivity.java +++ b/Android/MobiAds/src/de/android/mobiads/MobiAdsLoginActivity.java @@ -23,7 +23,6 @@ import android.app.DialogFragment; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.Resources; import android.os.Bundle; import android.os.StrictMode; import android.util.Log; @@ -84,7 +83,7 @@ public class MobiAdsLoginActivity extends Activity { case HttpStatus.SC_OK: String cookie = httpResponse.getLastHeader(SETCOOKIEFIELD).getValue(); if (cookie != null) { - CookieManager.getInstance().setCookie("users.mobiads.gumartinm.name",cookie); + CookieManager.getInstance().setCookie(getResources().getString(R.string.url_web),cookie); CookieSyncManager.getInstance().sync(); //Go to the next activity StrictMode.setThreadPolicy(currentPolicy); diff --git a/Android/MobiAds/src/de/android/mobiads/MobiAdsService.java b/Android/MobiAds/src/de/android/mobiads/MobiAdsService.java index baca137..03642b6 100644 --- a/Android/MobiAds/src/de/android/mobiads/MobiAdsService.java +++ b/Android/MobiAds/src/de/android/mobiads/MobiAdsService.java @@ -45,12 +45,12 @@ public class MobiAdsService extends Service { @Override public void onCreate() { - notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); - // Display a notification about us starting. - showNotification(); + //There should not be more than one thread using mobiAdsBatch field, see: + //http://developer.android.com/guide/topics/fundamentals/services.html#LifecycleCallbacks + //Otherwise there could be issues about sharing this field... this.mobiAdsBatch = new MobiAdsBatch(this.getResources().getString(R.string.user_agent_web_service), - this.getResources().getString(R.string.encoded_web_service)); + this.getResources().getString(R.string.encoded_web_service), this); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); @@ -98,6 +98,10 @@ public class MobiAdsService extends Service { // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(0, 10, criteria, locationListener, null); + + notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + // Display a notification about us starting. + showNotification(); } diff --git a/Android/MobiAds/src/de/android/mobiads/batch/MobiAdsBatch.java b/Android/MobiAds/src/de/android/mobiads/batch/MobiAdsBatch.java index 9e77e37..b9fdd74 100644 --- a/Android/MobiAds/src/de/android/mobiads/batch/MobiAdsBatch.java +++ b/Android/MobiAds/src/de/android/mobiads/batch/MobiAdsBatch.java @@ -1,25 +1,58 @@ package de.android.mobiads.batch; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.params.CoreProtocolPNames; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; import android.location.Location; +import android.net.Uri; import android.net.http.AndroidHttpClient; import android.util.Log; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import de.android.mobiads.R; +import de.android.mobiads.provider.Indexer; public class MobiAdsBatch { private static final String TAG = "MobiAdsBatch"; private static final int tasksMax = 10; private final ExecutorService exec = Executors.newFixedThreadPool(tasksMax); - private final String encoded; private final AndroidHttpClient httpClient; + private final Context context; + private final String mobiAdsCookie; - public MobiAdsBatch (String userAgent, String encoded) { - this.encoded = encoded; - + public MobiAdsBatch (String userAgent, String encoded, Context context) { + this.context = context; this.httpClient = AndroidHttpClient.newInstance(userAgent); + + this.httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, encoded); + this.httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); + + CookieSyncManager.createInstance(this.context); + this.mobiAdsCookie = CookieManager.getInstance().getCookie(this.context.getResources().getString(R.string.url_web)); } @@ -48,20 +81,202 @@ public class MobiAdsBatch { public void endBatch() { this.exec.shutdown(); + this.httpClient.close(); } private class Batch implements Runnable { + private final URL url; private Batch (URL url) { - + this.url = url; } @Override public void run() { - // TODO Auto-generated method stub + ResponseHandler handler = new ResponseHandler() { + public StringBuilder handleResponse(HttpResponse response) throws ClientProtocolException, IOException { + //There could be a null as return value in case of not receiving any data from the server, + //although the HTTP connection was OK. + return sortResponse(response); + } + }; + + try { + final HttpGet httpGet = new HttpGet(); + + httpGet.setHeader("Cookie", MobiAdsBatch.this.mobiAdsCookie); + try { + httpGet.setURI(this.url.toURI()); + StringBuilder builder = httpClient.execute(httpGet, handler); + JSONTokener tokener = new JSONTokener(builder.toString()); + JSONArray finalResult = new JSONArray(tokener); + Uri uriInsert = null; + + //TODO: finalResult.length() -1? Maybe I should remove the last semicolon in the JSON response. + for (int i = 0; i < (finalResult.length() -1); i++) { + JSONObject objects = finalResult.getJSONObject(i); + if ((uriInsert = updatedIndexer(objects)) != null) { + try { + downloadAds((String)objects.get("domain"), (String)objects.get("link"), (String) objects.get("id")); + } catch (Throwable e1) { + //In case of any error, remove the index database and the file + //or chunk successfully stored before the error. + try { + MobiAdsBatch.this.context.getContentResolver().delete(uriInsert, null, null); + MobiAdsBatch.this.context.deleteFile((String) objects.get("id")); + } catch (Throwable e2) { + // Log this exception. The original exception (if there is one) is more + // important and will be thrown to the caller. + Log.w("Error removing content after an exception.", e2); + } + + //Besides throw the original exception. + if (e1 instanceof Error) { + throw (Error) e1; + } + if (e1 instanceof RuntimeException) { + throw (RuntimeException) e1; + } + if (e1 instanceof Exception) { + throw (IOException) e1; + } + //throwing Throwable. At least the original exception is not lost :/ + throw e1; + } + } + + } + } catch (URISyntaxException e) { + Log.e(TAG, "Error while creating URI from URL.", e); + } catch (ClientProtocolException e) { + Log.e(TAG, "Error while executing HTTP client connection.", e); + } catch (UnsupportedEncodingException e) { + Log.e(TAG, "Error InputStreamReader.", e); + } catch (IOException e) { + Log.e(TAG, "Error while executing HTTP client connection.", e); + } catch (JSONException e) { + Log.e(TAG, "Error while parsing JSON response.", e); + } + } catch (Throwable e) { + //Not sure if it is "legal" to catch Throwable... + Log.e(TAG, "Caught exception, something went wrong", e); + } + } + + public StringBuilder sortResponse(HttpResponse httpResponse) throws IOException { + StringBuilder builder = null; + + if (httpResponse != null) { + switch (httpResponse.getStatusLine().getStatusCode()) { + case HttpStatus.SC_OK: + //OK + HttpEntity entity = httpResponse.getEntity(); + if (entity != null) { + //outside try/catch block. + //In case of exception it is thrown, otherwise instream will not be null and we get into the try/catch block. + InputStreamReader instream = new InputStreamReader(entity.getContent()/*, entity.getContentEncoding().getValue()*/); + try { + BufferedReader reader = new BufferedReader(instream); + builder = new StringBuilder(); + String currentLine = null; + currentLine = reader.readLine(); + while (currentLine != null) { + builder.append(currentLine).append("\n"); + currentLine = reader.readLine(); + } + } finally { + //instream will never be null in case of reaching this code, cause it was initialized outside try/catch block. + //In case of exception here, it is thrown to the upper layer. + instream.close(); + } + } + break; + case HttpStatus.SC_UNAUTHORIZED: + //ERROR IN USERNAME OR PASSWORD + throw new SecurityException("Unauthorized access: error in username or password."); + case HttpStatus.SC_BAD_REQUEST: + //WHAT THE HECK ARE YOU DOING? + throw new IllegalArgumentException("Bad request."); + default: + throw new IllegalArgumentException("Error while retrieving the HTTP status line."); + } + } + return builder; + } + + public void downloadAds(String domain, String link, String path) + throws MalformedURLException, URISyntaxException, FileNotFoundException, IOException { + final HttpGet httpGet = new HttpGet(); + final String URLAd = "http://" + domain + "/" + link; + HttpResponse httpResponse = null; + URL url = null; + OutputStream outputStream = null; + try { + url = new URL(URLAd); + httpGet.setURI(url.toURI()); + //By default max 2 connections at the same time per host. + //and infinite time out (we could wait here forever if we do not use a timeout see: 2.1. Connection parameters + //http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html) The same for execute with handler. + httpResponse = MobiAdsBatch.this.httpClient.execute(httpGet); + + if (httpResponse != null) { + switch (httpResponse.getStatusLine().getStatusCode()) { + case HttpStatus.SC_OK: + outputStream = MobiAdsBatch.this.context.openFileOutput(path, Context.MODE_PRIVATE); + try { + httpResponse.getEntity().writeTo(outputStream); + } finally { + //Closing the outputStream + outputStream.close(); + } + break; + case HttpStatus.SC_UNAUTHORIZED: + //ERROR IN USERNAME OR PASSWORD + throw new SecurityException("Unauthorized access: error in username or password."); + case HttpStatus.SC_BAD_REQUEST: + //WHAT THE HECK ARE YOU DOING? + throw new IllegalArgumentException("Bad request."); + default: + throw new IllegalArgumentException("Error while retrieving the HTTP status line."); + } + } + } finally { + try { + if (httpResponse != null) { + HttpEntity entity = httpResponse.getEntity(); + if (entity != null) { + entity.consumeContent(); + } + } + } catch (Throwable e) { + // Log this exception. The original exception (if there is one) is more + // important and will be thrown to the caller. See: {@link AbstractHttpClient} + Log.w("Error consuming content after an exception.", e); + } + } } + public Uri updatedIndexer (JSONObject objects) throws JSONException { + Uri updated = null; + Uri uri = Uri.parse("content://" + "de.android.mobiads.provider" + "/" + "indexer" + "/idad/" + objects.get("id")); + + synchronized (MobiAdsBatch.this) { + Cursor cursor = MobiAdsBatch.this.context.getContentResolver().query(uri, null, null, null, null); + + if (cursor != null) { + if (!cursor.moveToFirst()) { + //If the advertisement was not stored on the database + ContentValues values = new ContentValues(); + values.put(Indexer.Index.COLUMN_NAME_ID_AD, new Integer((String) objects.get("id"))); + values.put(Indexer.Index.COLUMN_NAME_PATH, (String) objects.get("id")); + updated = MobiAdsBatch.this.context.getContentResolver().insert(Indexer.Index.CONTENT_ID_URI_BASE, values); + } + cursor.close(); + } + } + return updated; + } } }