Hi. I'm (desperately) trying to get remote notification delivered to my app on iOS and Android versions.
I've setup a "subscription" web server which accepts devices id (registrations). I've setup a push server based on PushSharp to push messages to APNS and Gcm.
So far everything works perfectly fine with iOS.
In Android I don't really understand how to make it work.
I've followed this tutorial:
I've double checked permissions in the manifest, and I've implemented BroadcastReceivers and Services as told in the tutorial.
Everything works fine when the app is active (either running or in background) but when the app is not running nothing happens at all.
I don't really understand how to get the system to call my service in this situation.
Since debugging is almost impossible when the app is not running, I've simplified the code executed upon notification reception.
Here is the code snippet that should deal with notifications. The call to PushIntentService.DumpInfo just logs something before doing anything else:
` [BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")] [IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] {"@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] {"@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@PACKAGE_NAME@"})] public class MSoftGCMBroadcastReceiver : BroadcastReceiver { public const string TAG = "PushHandlerBroadcastReceiver";
public override void OnReceive(Context context, Intent intent)
{
PushIntentService.DumpInfo (context, intent);
PushIntentService.RunIntentInService(context, intent);
SetResult(Result.Ok, null, null);
}
}
[BroadcastReceiver] [IntentFilter(new[] { global::Android.Content.Intent.ActionBootCompleted })] public class MSoftGCMBootReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { PushIntentService.DumpInfo (context, intent); PushIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } }
[Service] public class PushIntentService : IntentService { private static PowerManager.WakeLock sWakeLock; private static object LOCK = new object();
public static void DumpInfo(Context context, Intent intent)
{
string RootDir = "/mnt/sdcard/msoft/" + context.ApplicationInfo.PackageName + "/log";
Directory.CreateDirectory (RootDir);
StreamWriter log = File.AppendText(RootDir + "/dump.log");
string prefix = DateTime.Now.ToString ("G") + " ";
log.Write (prefix + "ApplicationInfo ClassName={0} Icon={1} Name={2} ProcessName={3}\n",
context.ApplicationInfo.ClassName,
context.ApplicationInfo.Icon,
context.ApplicationInfo.Name,
context.ApplicationInfo.ProcessName);
log.Write (prefix + "MainActivity loaded={0}\n", (MainActivity.Main != null));
log.Write (prefix + "Global initialized={0}\n", (AndroidGlobal.AndroidInstance != null));
log.Write(prefix + "Intent Action={0} Categories={1}\n",
intent.Action,
String.Join(",", intent.Categories ?? new string[] { }));
log.Write(prefix + "Intent DataString={0} Extras={1}\n",
intent.DataString,
String.Join(",", intent.Extras.KeySet()));
log.Close();
}
public static void RunIntentInService(Context context, Intent intent)
{
lock (LOCK)
{
if (sWakeLock == null)
{
var pm = PowerManager.FromContext(context);
sWakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "MSoftPushWakeLogTag");
}
}
sWakeLock.Acquire();
intent.SetClass(context, typeof(PushIntentService));
context.StartService(intent);
}
protected override void OnHandleIntent(Intent intent)
{
try
{
switch (intent.Action) {
case "com.google.android.c2dm.intent.REGISTRATION":
PushClient.RegisterDevice(intent);
break;
case "com.google.android.c2dm.intent.RECEIVE":
PushClient.HandleMessage(intent);
break;
}
}
finally
{
lock (LOCK)
{
if (sWakeLock != null) sWakeLock.Release();
}
}
}
} `
Permission are also set in AssemblyInfo.cs:
[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
[assembly: UsesPermission(Name = "android.permission.RECEIVE_BOOT_COMPLETED")]
On REGISTRATION and RECEIVE events the dump file gets updated, but only when the app is loaded and active or running in background....
Any clue?
Thanks.