Hi,
I am trying to create Unity application that shows notification in statusbar. The application should be launched by tap on notification.
But I got the problem with implementation of such functionality. Sometime application is not launched. It looks like that:
- User executes application from launcher.
- User presses HOME button (onPause, onStope handlers of application activity are executed)
- User opens status bar and clicks on application notification.
- The application is not executed (there are some errors in the log, see below).
- Now user opens status bar second time and clicks on application notification again.
- The application is launched correctly.
The error (step 4) in the log looks like that:
02-07 11:14:02.425: I/ActivityManager(444): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x3400c000 Htcflg=0x1 cmp=com.example.u2aTest/.MyMainActivity bnds=[0,392][720,520] u=0} from pid -1
02-07 11:14:02.455: I/StatusBar(587): notificationClick intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x3400c000 Htcflg=0x1 cmp=com.example.u2aTest/.MyMainActivity } intentFlag:1
02-07 11:14:02.465: I/Unity(24826): onDestroy
02-07 11:14:02.470: D/Unity(24826): onDetachedFromWindow
02-07 11:14:02.490: D/Process(24826): killProcess, pid=24826
02-07 11:14:02.495: D/Process(24826): dalvik.system.VMStack.getThreadStackTrace(Native Method)
02-07 11:14:02.495: D/Process(24826): java.lang.Thread.getStackTrace(Thread.java:599)
02-07 11:14:02.495: D/Process(24826): android.os.Process.killProcess(Process.java:944)
02-07 11:14:02.495: D/Process(24826): com.unity3d.player.UnityPlayer.kill(Unknown Source)
02-07 11:14:02.495: D/Process(24826): com.unity3d.player.UnityPlayer.quit(Unknown Source)
02-07 11:14:02.495: D/Process(24826): com.unity3d.player.UnityPlayerActivity.onDestroy(Unknown Source)
02-07 11:14:02.495: D/Process(24826): android.app.Activity.performDestroy(Activity.java:5255)
02-07 11:14:02.495: D/Process(24826): android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1135)
02-07 11:14:02.495: D/Process(24826): android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3761)
02-07 11:14:02.495: D/Process(24826): android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3811)
02-07 11:14:02.495: D/Process(24826): android.app.ActivityThread.access$1200(ActivityThread.java:151)
02-07 11:14:02.495: D/Process(24826): android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
02-07 11:14:02.500: D/Process(24826): android.os.Handler.dispatchMessage(Handler.java:99)
02-07 11:14:02.500: D/Process(24826): android.os.Looper.loop(Looper.java:155)
02-07 11:14:02.500: D/Process(24826): android.app.ActivityThread.main(ActivityThread.java:5485)
02-07 11:14:02.500: D/Process(24826): java.lang.reflect.Method.invokeNative(Native Method)
02-07 11:14:02.500: D/Process(24826): java.lang.reflect.Method.invoke(Method.java:511)
02-07 11:14:02.500: D/Process(24826): com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
02-07 11:14:02.500: D/Process(24826): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
02-07 11:14:02.500: D/Process(24826): dalvik.system.NativeStart.main(Native Method)
02-07 11:14:02.530: D/InputManager(444): setFocusedApplication Exception: java.lang.NullPointerException
02-07 11:14:02.530: I/WindowState(444): WIN DEATH: Window{41c7ae60 com.example.u2aTest/com.example.u2aTest.MyMainActivity paused=true}
02-07 11:14:02.530: I/ActivityManager(444): Recipient 24826
02-07 11:14:02.530: I/ActivityManager(444): Process com.example.u2aTest (pid 24826) has died.
02-07 11:14:02.530: W/ActivityManager(444): Force removing ActivityRecord{41a33e88 com.example.u2aTest/.MyMainActivity}: app died, no saved state
The log for correct behavior (step 6) looks differently:
02-07 11:15:11.870: I/ActivityManager(444): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x3400c000 Htcflg=0x1 cmp=com.example.u2aTest/.MyMainActivity bnds=[0,392][720,520] u=0} from pid -1
02-07 11:15:11.890: I/StatusBar(587): notificationClick intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x3400c000 Htcflg=0x1 cmp=com.example.u2aTest/.MyMainActivity } intentFlag:1
02-07 11:15:11.915: I/ActivityManager(444): Start proc com.example.u2aTest for activity com.example.u2aTest/.MyMainActivity: pid=25141 uid=10034 gids={1015, 3003, 1028}
02-07 11:15:12.010: I/ActivityManager(444): Recipient 24972
02-07 11:15:12.185: D/PhoneStatusBar(587): disable: < expand icons alerts ticker* system_info back home recent clock >
02-07 11:15:12.195: W/dalvikvm(587): disableGcForExternalAlloc: false
02-07 11:15:16.140: I/Unity(25141): cpuarch.GetCpuFeatures() = 254
02-07 11:15:16.140: I/Unity(25141): cpuarch.GetTotalMemory() = 971
02-07 11:15:16.145: I/Unity(25141): gles_mode = 2 (integer)
02-07 11:15:16.145: I/Unity(25141): splash_mode = 0 (integer)
02-07 11:15:16.145: I/Unity(25141): hide_status_bar = True (bool)
02-07 11:15:16.145: I/Unity(25141): 32bit_display = False (bool)
02-07 11:15:16.145: I/Unity(25141): 24bit_depth = False (bool)
02-07 11:15:16.145: I/Unity(25141): default_aa = 0 (integer)
02-07 11:15:16.145: I/Unity(25141): useObb = False (bool)
02-07 11:15:16.145: I/Unity(25141): development_player = True (bool)
02-07 11:15:16.365: E/(25141): file /data/data/com.nvidia.NvCPLSvc/files/driverlist.txt: not found!
02-07 11:15:16.365: I/(25141): Attempting to load EGL implementation /system/lib//egl/libEGL_tegra_impl
02-07 11:15:16.380: I/(25141): Loaded EGL implementation /system/lib//egl/libEGL_tegra_impl
02-07 11:15:16.400: I/Unity(25141): onResume
02-07 11:15:16.400: I/Unity(25141): windowFocusChanged: true
02-07 11:15:16.425: D/Unity(25141): surfaces: attach glview
02-07 11:15:16.455: I/com.example.u2aTest(25141): MyMainActivity.onCreate
02-07 11:15:16.500: I/Unity(25141): onResume
02-07 11:15:16.500: I/com.example.u2aTest(25141): MyMainActivity.onResume
I have written to Unity support and got answer:
“this is not a unity issue. Try the forums for help. Some hints. Add android:launchMode=“singleTask” to the manifest. Fix your launch flags on the Intent.”
But actually I have tried to use all possible variants of launchMode with different combinations of Intent flags with no results - errors in logs are not changed. I have tried: no flags, FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP. Intent has some (other flags), but I suspect they are not applicable in this case.
I have created test android application that uses android-plugin as a library project and calls exactly same code - everything works fine.
According to log the problem is here:
I/Unity(23208): onDestroy
D/Unity(23208): onDetachedFromWindow
com.unity3d.player.UnityPlayer.kill(Unknown Source)
com.unity3d.player.UnityPlayer.quit(Unknown Source)
com.unity3d.player.UnityPlayerActivity.onDestroy(Unknown Source)
WIN DEATH: Window{420aa7b8 com.example.u2aTest/com.example.u2aTest.MyMainActivity paused=true}
Process com.example.u2aTest (pid 10205) has died.
The process is died and new instance of application is not launched…
Has anybody any idea how to fix/workaround the problem?
P.s. I have created simple empty project, that could demonstrate the problem:
http://code.google.com/p/dvsrc/downloads/detail?name=status_bar_notification_launch.7z
This is manifest of test application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mobilityflow.w3d"
android:versionCode="2"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application android:name="com.example.u2aTest.Kernel" android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:name=".MyMainActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
android:launchMode="singleTop"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
>
</application>
</manifest>
This is a code to create notification:
public static void showNotification(Context context) {
final Intent result_intent = new Intent(context, MyMainActivity.class);
result_intent.setAction(Intent.ACTION_MAIN);
result_intent.addCategory(Intent.CATEGORY_LAUNCHER);
result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
//result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
TaskStackBuilder stack_builder = TaskStackBuilder.create(context);
stack_builder.addParentStack(MyMainActivity.class);
stack_builder.addNextIntent(result_intent);
PendingIntent pending_intent = stack_builder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
android.support.v4.app.NotificationCompat.Builder builder = new android.support.v4.app.NotificationCompat.Builder(context);
Resources res = context.getResources();
builder.setContentIntent(pending_intent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
.setTicker("test")
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setContentTitle("title")
.setContentInfo("cinfo")
.setContentText("ctext");
Notification n = builder.build();
n.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIF_ID, n);
}
P.s.s. I have found description for the similar issue for xamarin application:
https://github.com/mono/MonoGame/issues/1126
The problem was “This was an infinite loop on the texture reloading that I was doing when the android activity resumed from the lock screen or prior-apps screen.”. But this solution is not applicable in my case…