diff --git a/.gitignore b/.gitignore index a051216..57dfd66 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ hermes/build hermesexample/build hermes/hermes.iml hermesexample/hermesexample.iml -gradle.properties \ No newline at end of file +gradle.properties +gradlew.bat \ No newline at end of file diff --git a/hermes/build.gradle b/hermes/build.gradle index 212f215..496016d 100644 --- a/hermes/build.gradle +++ b/hermes/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" + compileSdkVersion 22 + buildToolsVersion "22.0.1" defaultConfig { minSdkVersion 9 - targetSdkVersion 21 + targetSdkVersion 22 versionCode 1 versionName "1.0" } @@ -20,7 +20,8 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.google.android.gms:play-services-gcm:7.0.0' + compile 'com.android.support:support-v4:22.1.1' + compile 'com.google.android.gms:play-services-gcm:7.3.0' } apply from: "../maven.gradle" diff --git a/hermes/src/main/AndroidManifest.xml b/hermes/src/main/AndroidManifest.xml index 86d9926..c7373ce 100644 --- a/hermes/src/main/AndroidManifest.xml +++ b/hermes/src/main/AndroidManifest.xml @@ -5,16 +5,12 @@ + - - () { @Override - protected Object doInBackground(Object[] params) { + protected String doInBackground(Object[] params) { String msg = ""; try { if (gcm == null) { @@ -166,7 +170,7 @@ protected Object doInBackground(Object[] params) { } regID = gcm.register(SENDER_ID); msg = "Device registered, registration ID=" + regID; - + Log.d("Hermes", "From Async - "+msg); // You should send the registration ID to your server over HTTP, // so it can use GCM/HTTP or CCS to send messages to your app. // The request to your server should be authenticated if your app @@ -179,11 +183,17 @@ protected Object doInBackground(Object[] params) { // Persist the registration ID - no need to register again. storeRegistrationId(context, regID); + if (CALLBACK != null){ + CALLBACK.registrationComplete(regID); + } } catch (IOException ex) { msg = "Error :" + ex.getMessage(); // If there is an error, don't just keep trying to register. // Require the user to click a button again, or perform // exponential back-off. + ExponentialBackoffReceiver.attemptRegistration(context, + Hermes.getDelay(), + Hermes.getSenderId()); } return msg; } @@ -199,11 +209,11 @@ protected Object doInBackground(Object[] params) { private void storeRegistrationId(Context context, String regId) { final SharedPreferences prefs = getGCMPreferences(context); int appVersion = getAppVersion(context); - Log.i(TAG, "Saving regId on app version " + appVersion); + Log.d("Hermes", "Saving regId on app version " + appVersion); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PROPERTY_REG_ID, regId); editor.putInt(PROPERTY_APP_VERSION, appVersion); - editor.commit(); + editor.apply(); } /** diff --git a/hermes/src/main/java/in/raveesh/hermes/receivers/ExponentialBackoffReceiver.java b/hermes/src/main/java/in/raveesh/hermes/receivers/ExponentialBackoffReceiver.java index 2aa38fe..96b7a97 100644 --- a/hermes/src/main/java/in/raveesh/hermes/receivers/ExponentialBackoffReceiver.java +++ b/hermes/src/main/java/in/raveesh/hermes/receivers/ExponentialBackoffReceiver.java @@ -22,7 +22,7 @@ public static void attemptRegistration(Context context, int time, String sender_ PendingIntent pendingIntent = PendingIntent.getBroadcast(context, time, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); manager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, pendingIntent); - Log.d(Hermes.TAG, "Exponential Backoff Set for " + time); + Log.d("Hermes", "Exponential Backoff Set for " + time); if (Hermes.CALLBACK != null){ Hermes.CALLBACK.setExponentialBackoff(time); } @@ -37,7 +37,7 @@ public void onReceive(Context context, Intent intent) { if (Hermes.CALLBACK != null){ Hermes.CALLBACK.backoffComplete(backedOff); } - Log.d(Hermes.TAG, "Exponential backoff complete after "+ backedOff); + Log.d("Hermes", "Exponential backoff complete after " + backedOff); Hermes.register(context, intent.getStringExtra(EXTRA_SENDER_ID)); Hermes.setDelay(backedOff*2); } diff --git a/hermes/src/main/java/in/raveesh/hermes/receivers/HermesBroadcastReceiver.java b/hermes/src/main/java/in/raveesh/hermes/receivers/HermesBroadcastReceiver.java index 2066b4e..c105f68 100644 --- a/hermes/src/main/java/in/raveesh/hermes/receivers/HermesBroadcastReceiver.java +++ b/hermes/src/main/java/in/raveesh/hermes/receivers/HermesBroadcastReceiver.java @@ -1,38 +1,53 @@ package in.raveesh.hermes.receivers; -import android.content.BroadcastReceiver; +import android.app.Activity; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.support.v4.content.WakefulBroadcastReceiver; import android.util.Log; -import in.raveesh.hermes.Hermes; - -public class HermesBroadcastReceiver extends BroadcastReceiver { +/** + * This {@code HermesBroadcastReceiver} takes care of creating and managing a + * partial wake lock for your app. It passes off the work of processing the GCM + * message to {@code HermesIntentService}. + * + * The wakelock is release when {@code HermesIntentService} calls + * {@code completeWakefulIntent()} + * + */ +public class HermesBroadcastReceiver extends WakefulBroadcastReceiver { + private Class intentService; public HermesBroadcastReceiver() { } - protected boolean gotRegistrationId = false; - protected boolean error = false; - protected String registrationID; + /** + * This sets the class which should be called when the GCM message is + * received. + * This method should be called when creating the BroadcastReceiver, preferably in the + * constructor. When {@code onReceive} is called, the @param intentService class would + * be called to process the message + * @param intentService the intent service class which should be called to process the gcm + * message. Should extend {@code HermesIntentService} + */ + public void setIntentService(Class intentService) { + this.intentService = intentService; + Log.d("Hermes", "Setting intentService class to - " + intentService); + } @Override public void onReceive(Context context, Intent intent) { - registrationID = intent.getStringExtra("registration_id"); - if (registrationID != null) { - gotRegistrationId = true; - if (Hermes.CALLBACK != null) { - Hermes.CALLBACK.registrationComplete(registrationID); - } - } else if (intent.getExtras() != null && intent.getExtras().get("error") != null) { - error = true; - if (Hermes.CALLBACK != null){ - Hermes.CALLBACK.registrationFailed(intent.getExtras().get("error").toString()); - } - ExponentialBackoffReceiver.attemptRegistration(context, Hermes.getDelay(), Hermes.getSenderId()); - } else { - Log.d(Hermes.TAG, "GCM Message Received"); - - } + + if(intentService == null ) throw new UnsupportedOperationException( + "Please use setIntentService in the " + + "constructor of your broadcastReceiver class."); + + ComponentName comp = new ComponentName( + context.getPackageName(), + intentService.getName()); + + startWakefulService(context, (intent.setComponent(comp))); + setResultCode(Activity.RESULT_OK); } } diff --git a/hermes/src/main/java/in/raveesh/hermes/receivers/HermesIntentService.java b/hermes/src/main/java/in/raveesh/hermes/receivers/HermesIntentService.java new file mode 100644 index 0000000..8d6bfdc --- /dev/null +++ b/hermes/src/main/java/in/raveesh/hermes/receivers/HermesIntentService.java @@ -0,0 +1,79 @@ +package in.raveesh.hermes.receivers; + +import android.app.IntentService; +import android.content.Intent; +import android.util.Log; + +import com.google.android.gms.gcm.GoogleCloudMessaging; + +import in.raveesh.hermes.Hermes; + +/** + * Handles the intent which contains the GCM message. + * It holds the wake lock started by {@code HermesBroadcastReceiver} while + * doing the computation and finally releases it by calling + * {@code completeWakefulIntent()} + * + * This class is abstract and methods + * {@code messageReceived}, {@code messageDeleted}, {@code messageSendError}, + * {@code messageSendEvent} should be overridden in the subclass. + * + */ +public abstract class HermesIntentService extends IntentService{ + protected boolean gotRegistrationId = false; + protected boolean error = false; + protected String registrationID; + + public HermesIntentService(String name) { + super(name); + } + + @Override + protected void onHandleIntent(Intent intent) { + Log.d("Hermes", "Received intent in HermesIntentService with action - "+intent.getAction()); + + if(intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) { + registrationID = intent.getStringExtra("registration_id"); + if (registrationID != null) { + gotRegistrationId = true; + if (Hermes.CALLBACK != null) { + Hermes.CALLBACK.registrationComplete(registrationID); + } + } else if (intent.getExtras() != null && intent.getExtras().get("error") != null) { + error = true; + if (Hermes.CALLBACK != null){ + Hermes.CALLBACK.registrationFailed(intent.getExtras().get("error").toString()); + } + + // Registration message was received but was error. + ExponentialBackoffReceiver.attemptRegistration(this, Hermes.getDelay(), Hermes.getSenderId()); + } + } else if(intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { + GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); + String messageType = gcm.getMessageType(intent); + + // Logging and calling the appropriate abstract method. + if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { + Log.d("Hermes", "Message Received"); + messageReceived(); + } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { + Log.d("Hermes", "Message Deleted"); + messageDeleted(); + } else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { + Log.d("Hermes", "Message Send Error"); + messageSendError(); + } else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_EVENT.equals(messageType)) { + Log.d("Hermes", "Message Send Event"); + messageSendEvent(); + } + } + + // Release the wake lock provided by the WakefulBroadcastReceiver. + HermesBroadcastReceiver.completeWakefulIntent(intent); + } + + public abstract void messageReceived(); + public abstract void messageDeleted(); + public abstract void messageSendEvent(); + public abstract void messageSendError(); +} diff --git a/hermesexample/build.gradle b/hermesexample/build.gradle index a1c3873..62c5253 100644 --- a/hermesexample/build.gradle +++ b/hermesexample/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" + compileSdkVersion 22 + buildToolsVersion "22.0.1" defaultConfig { applicationId "in.raveesh.hermesexample" minSdkVersion 9 - targetSdkVersion 21 + targetSdkVersion 22 versionCode 1 versionName "1.0" } @@ -25,6 +25,8 @@ repositories { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.0.0' - compile 'in.raveesh:hermes:0.1.0-SNAPSHOT' + compile 'com.android.support:appcompat-v7:22.1.1' +// compile 'in.raveesh:hermes:0.1.0-SNAPSHOT' + + compile project (':hermes') // For Development } diff --git a/hermesexample/src/main/AndroidManifest.xml b/hermesexample/src/main/AndroidManifest.xml index 49d4954..0926556 100644 --- a/hermesexample/src/main/AndroidManifest.xml +++ b/hermesexample/src/main/AndroidManifest.xml @@ -37,6 +37,9 @@ + + diff --git a/hermesexample/src/main/java/in/raveesh/hermesexample/GcmBroadcastReceiver.java b/hermesexample/src/main/java/in/raveesh/hermesexample/GcmBroadcastReceiver.java index 9790f0e..70c962b 100644 --- a/hermesexample/src/main/java/in/raveesh/hermesexample/GcmBroadcastReceiver.java +++ b/hermesexample/src/main/java/in/raveesh/hermesexample/GcmBroadcastReceiver.java @@ -2,27 +2,20 @@ import android.content.Context; import android.content.Intent; -import android.util.Log; import in.raveesh.hermes.receivers.HermesBroadcastReceiver; public class GcmBroadcastReceiver extends HermesBroadcastReceiver { public GcmBroadcastReceiver() { + // IMPORTANT + // Call this with the intentservice class you want to start + // Refer javadoc for more info. + setIntentService(GcmIntentService.class); } + @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); - if (gotRegistrationId){ - /** - * Device has just been registered. - */ - Log.d("HermesExample", "Device Registered, ID is "+registrationID); - } - else if (!error){ - /** - * GCM Message received, handle it as per your requirements - */ - } } } diff --git a/hermesexample/src/main/java/in/raveesh/hermesexample/GcmIntentService.java b/hermesexample/src/main/java/in/raveesh/hermesexample/GcmIntentService.java new file mode 100644 index 0000000..c7b4e91 --- /dev/null +++ b/hermesexample/src/main/java/in/raveesh/hermesexample/GcmIntentService.java @@ -0,0 +1,32 @@ +package in.raveesh.hermesexample; + +import android.content.Intent; +import android.util.Log; + +import in.raveesh.hermes.receivers.HermesIntentService; + +public class GcmIntentService extends HermesIntentService { + + public GcmIntentService() { + super("GcmIntentService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + super.onHandleIntent(intent); + } + + @Override + public void messageReceived() { + Log.d("HermesExample", "Message Received in overridden method"); + } + + @Override + public void messageDeleted() {} + + @Override + public void messageSendEvent() {} + + @Override + public void messageSendError() {} +} diff --git a/hermesexample/src/main/java/in/raveesh/hermesexample/MainActivity.java b/hermesexample/src/main/java/in/raveesh/hermesexample/MainActivity.java index fca1b8b..f44d953 100644 --- a/hermesexample/src/main/java/in/raveesh/hermesexample/MainActivity.java +++ b/hermesexample/src/main/java/in/raveesh/hermesexample/MainActivity.java @@ -1,17 +1,15 @@ package in.raveesh.hermesexample; -import android.support.v7.app.ActionBarActivity; import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.widget.TextView; -import in.raveesh.hermes.GcmRegistrationException; import in.raveesh.hermes.Hermes; import in.raveesh.hermes.RegistrationCallback; -public class MainActivity extends ActionBarActivity implements RegistrationCallback{ +public class MainActivity extends AppCompatActivity implements RegistrationCallback{ TextView textView; @@ -26,38 +24,75 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onResume(){ + Log.d("HermesExample", "onResume"); super.onResume(); Hermes.register(this, "893452105076"); } @Override protected void onPause(){ + Log.d("HermesExample", "onPause"); super.onPause(); Hermes.pause(this); } + /** + * Run all the UI changes task on the UI thread as these calls are called from a + * different thread from asynctask in {@code Hermes} + */ + @Override - public void registrationComplete(String id) { - textView.setText(id); + public void registrationComplete(final String id) { + Log.d("HermesExample", "registrationComplete"); + this.runOnUiThread(new Runnable() { + @Override + public void run() { + textView.setText(id); + } + }); } @Override public void registrationProcessStarted() { - textView.setText("Started Registration Process"); + Log.d("HermesExample", "registrationProcessStarted"); + this.runOnUiThread(new Runnable() { + @Override + public void run() { + textView.setText("Started Registration Process"); + } + }); } @Override - public void registrationFailed(String msg) { - textView.setText("Registration failed: "+msg); + public void registrationFailed(final String msg) { + Log.d("HermesExample", "registrationFailed"); + this.runOnUiThread(new Runnable() { + @Override + public void run() { + textView.setText("Registration failed: " + msg); + } + }); } @Override - public void setExponentialBackoff(int time) { - textView.setText("Set exponential backoff for "+time); + public void setExponentialBackoff(final int time) { + Log.d("HermesExample", "setExponentialBackoff"); + this.runOnUiThread(new Runnable() { + @Override + public void run() { + textView.setText("Set exponential backoff for " + time); + } + }); } @Override - public void backoffComplete(int time) { - textView.setText("Exponential backoff complete after "+time); + public void backoffComplete(final int time) { + Log.d("HermesExample", "backoffComplete"); + this.runOnUiThread(new Runnable() { + @Override + public void run() { + textView.setText("Exponential backoff complete after " + time); + } + }); } }