当应用不是 运行 时,无法从通知调用 activity 方法
Cannot call activity method from notification when app is NOT running
我有一个警报提醒,显示带有额外数据的通知。我想要做的是通过我的通知中的意图将额外数据发送到我的主要activity,然后打开应用程序并调用特定方法(位置信息) activity。该方法将在我已经通过的locationId
的基础上打开一个新的activity。
当我的应用程序在 后台 中 运行 时效果很好,但是当它被杀死时,即当应用程序完全关闭,它打开应用程序的主要activity,但不调用该方法。
我的通知代码用于发送意图数据:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("fromNotification", true);
intent.putExtra("locationId", locationId);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 111, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
这就是我对方法的称呼:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
}
我也试过在主 activity 的 onCreate 末尾添加 ,这应该是解决方案,但它什么也没做:
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
我尝试了很多解决方案(包括 this, this, this, , this, this, ,还有更多),但无法实现。
清单(只是主要的 activity 部分):
<application
android:name="com.weekendcoder.kemo.hotels.app.AppController"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
</application>
这是我理想的工作流程的描述 - 如果我单击通知,它应该打开我的 MainActivity,它有一个地图片段。在我的地图上加载所有内容后,我想从我的 activity 主地图开始一个新的 activity - 我想打开 locationDetails activity 使用我从通知。由于调试在我关闭应用程序后立即停止,因此我无法查明问题所在,但我尝试添加以下内容:
if (getIntent().hasExtra("fromNotification"))
{
Toast.makeText(MainActivity.this, "Notification!", Toast.LENGTH_LONG).show();
}
在我的 onCreate 开始时它确实显示了 toast。我不能在我的 onCreate 开始时使用这个条件,因为地图没有加载和设置,所以我在我的 onCreate 结束时添加它。在这种情况下,它永远不会被调用。
我可以通过直接从通知中打开新的 activity 来让它工作,但这不是我理想的解决方案。我希望能够在应用程序关闭时从通知中调用 activity 中的任何方法。
我也试过添加这个:
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId ");
CallFetchLocationInfoFromMapsFragment(locationId);
Toast.makeText(MainActivity.this, "Notification id: " locationId, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this, "No notification", Toast.LENGTH_LONG).show();
}
在我的 onCreate 结束时只是为了看看我是否可以显示这个值,但我一直在 "No notification" toast。
当我在 onCreate 的开头放置相同的 if 条件时,它崩溃了:
08-14 18:06:03.319 18591-18591/com.weekendcoder.kemo.hotels D/SQLiteHandler: Fetching notification settings from sqlite db
08-14 18:06:03.329 18591-18591/com.weekendcoder.kemo.hotels W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
08-14 18:06:03.384 18591-18591/com.weekendcoder.kemo.hotels D/AndroidRuntime: Shutting down VM
08-14 18:06:03.384 18591-18591/com.weekendcoder.kemo.hotels W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41cdc700)
08-14 18:06:03.389 18591-18591/com.weekendcoder.kemo.hotels E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.weekendcoder.kemo.hotels/com.weekendcoder.kemo.hotels.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2295)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2349)
at android.app.ActivityThread.access0(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.weekendcoder.kemo.hotels.sliderfragments.MapsFragment.fetchlocationDetails(MapsFragment.java:545)
at com.weekendcoder.kemo.hotels.MainActivity.CallFetchlocationDetailsFromMapsFragment(MainActivity.java:661)
at com.weekendcoder.kemo.hotels.MainActivity.onCreate(MainActivity.java:324)
at android.app.Activity.performCreate(Activity.java:5372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2257)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2349)
at android.app.ActivityThread.access0(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
编辑:
有一个可行的解决方案,但我对它不满意,想找到一些东西smarter/safer。解决方案是在开头获取 id,然后添加:
if (locationId != null) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
CallFetchLocationInfoFromMapsFragment(locationId);
}
}, 5000);
}
这将允许我的应用程序等待 5 秒,然后在所有其他方法执行后调用该方法。 这行得通,但我不确定这是继续进行此操作的最佳方式,某些设备可能会更慢。最好能找到一种方法检查onCreated是否完全执行完然后调用这个方法。
我想你需要这个
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
连同在清单
中为您的 activity 设置 singleTask 启动模式
<activity android:name=".YourActivity"
android:launchMode="singleTask">
...
</activity>
在评论中的讨论(以上)中,您表示您正在使用 launchMode="singleTask"
。这是一种特殊的启动模式,对您的应用来说不是必需的。它通常制造的问题多于解决的问题。请删除特殊启动模式,看看是否有帮助。完成此操作后,当您的应用不是 运行 时点击通知应该会启动该应用并创建 MainActivity
.
的新实例
也有可能您无法在 onCreate()
中执行您想执行的操作,因为您的 Fragment
尚未设置。你可能只需要记住你想在 onCreate()
中做什么(开始位置详细信息),但要等到 onResume()
或你设置好你的 Fragment
之后才真正去做。
我有一个警报提醒,显示带有额外数据的通知。我想要做的是通过我的通知中的意图将额外数据发送到我的主要activity,然后打开应用程序并调用特定方法(位置信息) activity。该方法将在我已经通过的locationId
的基础上打开一个新的activity。
当我的应用程序在 后台 中 运行 时效果很好,但是当它被杀死时,即当应用程序完全关闭,它打开应用程序的主要activity,但不调用该方法。
我的通知代码用于发送意图数据:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("fromNotification", true);
intent.putExtra("locationId", locationId);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 111, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
这就是我对方法的称呼:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
}
我也试过在主 activity 的 onCreate 末尾添加
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
我尝试了很多解决方案(包括 this, this, this,
清单(只是主要的 activity 部分):
<application
android:name="com.weekendcoder.kemo.hotels.app.AppController"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
</application>
这是我理想的工作流程的描述 - 如果我单击通知,它应该打开我的 MainActivity,它有一个地图片段。在我的地图上加载所有内容后,我想从我的 activity 主地图开始一个新的 activity - 我想打开 locationDetails activity 使用我从通知。由于调试在我关闭应用程序后立即停止,因此我无法查明问题所在,但我尝试添加以下内容:
if (getIntent().hasExtra("fromNotification"))
{
Toast.makeText(MainActivity.this, "Notification!", Toast.LENGTH_LONG).show();
}
在我的 onCreate 开始时它确实显示了 toast。我不能在我的 onCreate 开始时使用这个条件,因为地图没有加载和设置,所以我在我的 onCreate 结束时添加它。在这种情况下,它永远不会被调用。
我可以通过直接从通知中打开新的 activity 来让它工作,但这不是我理想的解决方案。我希望能够在应用程序关闭时从通知中调用 activity 中的任何方法。
我也试过添加这个:
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId ");
CallFetchLocationInfoFromMapsFragment(locationId);
Toast.makeText(MainActivity.this, "Notification id: " locationId, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this, "No notification", Toast.LENGTH_LONG).show();
}
在我的 onCreate 结束时只是为了看看我是否可以显示这个值,但我一直在 "No notification" toast。
当我在 onCreate 的开头放置相同的 if 条件时,它崩溃了:
08-14 18:06:03.319 18591-18591/com.weekendcoder.kemo.hotels D/SQLiteHandler: Fetching notification settings from sqlite db
08-14 18:06:03.329 18591-18591/com.weekendcoder.kemo.hotels W/Settings: Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
08-14 18:06:03.384 18591-18591/com.weekendcoder.kemo.hotels D/AndroidRuntime: Shutting down VM
08-14 18:06:03.384 18591-18591/com.weekendcoder.kemo.hotels W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41cdc700)
08-14 18:06:03.389 18591-18591/com.weekendcoder.kemo.hotels E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.weekendcoder.kemo.hotels/com.weekendcoder.kemo.hotels.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2295)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2349)
at android.app.ActivityThread.access0(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.weekendcoder.kemo.hotels.sliderfragments.MapsFragment.fetchlocationDetails(MapsFragment.java:545)
at com.weekendcoder.kemo.hotels.MainActivity.CallFetchlocationDetailsFromMapsFragment(MainActivity.java:661)
at com.weekendcoder.kemo.hotels.MainActivity.onCreate(MainActivity.java:324)
at android.app.Activity.performCreate(Activity.java:5372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2257)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2349)
at android.app.ActivityThread.access0(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
编辑:
有一个可行的解决方案,但我对它不满意,想找到一些东西smarter/safer。解决方案是在开头获取 id,然后添加:
if (locationId != null) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
CallFetchLocationInfoFromMapsFragment(locationId);
}
}, 5000);
}
这将允许我的应用程序等待 5 秒,然后在所有其他方法执行后调用该方法。 这行得通,但我不确定这是继续进行此操作的最佳方式,某些设备可能会更慢。最好能找到一种方法检查onCreated是否完全执行完然后调用这个方法。
我想你需要这个
if (getIntent().hasExtra("fromNotification")) {
String locationId = getIntent().getStringExtra("locationId");
CallFetchLocationInfoFromMapsFragment(locationId);
}
连同在清单
中为您的 activity 设置 singleTask 启动模式<activity android:name=".YourActivity"
android:launchMode="singleTask">
...
</activity>
在评论中的讨论(以上)中,您表示您正在使用 launchMode="singleTask"
。这是一种特殊的启动模式,对您的应用来说不是必需的。它通常制造的问题多于解决的问题。请删除特殊启动模式,看看是否有帮助。完成此操作后,当您的应用不是 运行 时点击通知应该会启动该应用并创建 MainActivity
.
也有可能您无法在 onCreate()
中执行您想执行的操作,因为您的 Fragment
尚未设置。你可能只需要记住你想在 onCreate()
中做什么(开始位置详细信息),但要等到 onResume()
或你设置好你的 Fragment
之后才真正去做。