Android MobiAds appliction working.
authorgumartinm <gu.martinm@gmail.com>
Wed, 21 Mar 2012 07:10:35 +0000 (08:10 +0100)
committergumartinm <gu.martinm@gmail.com>
Wed, 21 Mar 2012 07:10:35 +0000 (08:10 +0100)
Just is left to fix some issues about closing the sqlite database.

Android/MobiAds/gen/de/android/mobiads/R.java
Android/MobiAds/res/values/strings.xml
Android/MobiAds/src/de/android/mobiads/MobiAdsLoginActivity.java
Android/MobiAds/src/de/android/mobiads/MobiAdsService.java
Android/MobiAds/src/de/android/mobiads/batch/MobiAdsBatch.java

index 417c50b..93833a5 100644 (file)
@@ -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;
     }
 }
index 653249f..eb386ef 100644 (file)
@@ -20,6 +20,7 @@
     <string name="remote_service_stopped">MobiAds Service Stopped</string>
     <string name="remote_service_label">MobiAds Service</string>
     <string name="url_login_web_service">http://users.mobiads.gumartinm.name/userfront.php/api/login/auth.json</string>
+    <string name="url_web">users.mobiads.gumartinm.name</string>
     <string name="user_agent_web_service">MobieAds/1.0</string>
     <string name="encoded_web_service">UTF-8</string>
 
index 01435fe..cde859a 100644 (file)
@@ -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);
index baca137..03642b6 100644 (file)
@@ -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();
     }
     
     
index 9e77e37..b9fdd74 100644 (file)
@@ -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<StringBuilder> handler = new ResponseHandler<StringBuilder>() {
+                           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;
+               }
        }
 }