我这里有一个简单的webview活动,加载后会自动显示正在进行的通知。我们的想法是,人们可以远离此活动,并通过下拉菜单并选择它,从他们想要的任何屏幕再次快速访问它。然后,当他们想要时,他们可以通过点击菜单按钮并点击退出关闭通知,然后清除通知。一切正常。但是,当按下通知时,它会启动活动的新实例。我需要更改什么才能看到活动是否尚未被销毁,我可以回调用该实例(恢复它),因此不需要再次加载它,也不需要在我的堆栈中添加其他活动。有任何想法吗?任何帮助将不胜感激。
package com.my.app;
import com.flurry.android.FlurryAgent;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class Chat extends Activity {
private ProgressDialog progressBar;
public WebView webview;
private static final String TAG = "Main";
private NotificationManager mNotificationManager;
private int SIMPLE_NOTFICATION_ID;
@Override
public void onStart() {
super.onStart();
CookieSyncManager.getInstance().sync();
FlurryAgent.onStartSession(this, "H9QGMRC46IPXB43GYWU1");
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
final Notification notifyDetails = new Notification(R.drawable.chat_notification,"Chat Started",System.currentTimeMillis());
notifyDetails.flags |= Notification.FLAG_ONGOING_EVENT;
Context context = getApplicationContext();
CharSequence contentTitle = "Chat";
CharSequence contentText = "Press to return to chat";
Intent notifyIntent = new Intent(context, Chat.class);
PendingIntent intent =
PendingIntent.getActivity(Chat.this, 0,
notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent);
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
webview = (WebView) findViewById(R.id.webviewchat);
webview.setWebViewClient(new chatClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.loadUrl("http://google.com");
progressBar = ProgressDialog.show(Chat.this, "", "Loading Chat...");
}
private class chatClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "Processing webview url click...");
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
webview.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu (Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.chatmenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected (MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
Intent a = new Intent(this, Home.class);
startActivity(a);
return true;
case R.id.closechat:
mNotificationManager.cancel(SIMPLE_NOTFICATION_ID);
Intent v = new Intent(this, Home.class);
startActivity(v);
return true;
}
return false;
}
public void onStop() {
super.onStop();
CookieSyncManager.getInstance().sync();
FlurryAgent.onEndSession(this);
}
}
@Commonsware
为了确保我说得对,这是你的建议吗?
我有点担心这条线,
PendingIntent.getActivity(Chat.this, 0, notifyIntent, SIMPLE_NOTFICATION_ID);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
final Notification notifyDetails = new Notification(R.drawable.chat_notification,"Chat Started",System.currentTimeMillis());
notifyDetails.flags |= Notification.FLAG_ONGOING_EVENT;
Context context = getApplicationContext();
CharSequence contentTitle = "Chat";
CharSequence contentText = "Press to return to chat";
Intent notifyIntent = new Intent(context, Chat.class);
PendingIntent intent =
PendingIntent.getActivity(Chat.this, 0, notifyIntent, SIMPLE_NOTFICATION_ID);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
webview = (WebView) findViewById(R.id.webviewchat);
webview.setWebViewClient(new chatClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.loadUrl("http://google.com");
progressBar = ProgressDialog.show(Chat.this, "", "Loading Chat...");
}
答案 0 :(得分:55)
这个想法是人们可以导航 远离这项活动而且很快 他们可以从任何屏幕再次访问它 希望通过下拉下拉 菜单并选择它。
请选择此选项。
但是,通知是 按下它开始一个新的实例 活动。
默认情况下会发生这种情况。
我需要做些什么来改变它 看活动还没有 被摧毁,我可以打电话 该实例返回(恢复它)和 因此无需再次加载 并且不需要添加其他活动 到我的堆栈。
摆脱FLAG_ACTIVITY_NEW_TASK
。添加notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
- 请参阅this sample project。
Context context = getApplicationContext();
请不要这样做。只需将Activity
用作Context
。
答案 1 :(得分:21)
这是我显示通知的方法。我希望它对你有所帮助。
private static void generateNotification(Context context, String message){
Intent notificationIntent = new Intent(context, YOUR_ACTIVITY.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getString(R.string.app_name))
.setContentIntent(intent)
.setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
答案 2 :(得分:14)
以防其他人遇到同样的困难......
我尝试了上面的所有代码但没有成功 - 通知项目一直在启动我的应用程序的全新实例,即使其中一个已经在运行。 (我只想让一个实例在任何时候都可用。)最后注意到另一个线程(https://stackoverflow.com/a/20724199/4307281),它在清单中需要一个简单的附加条目:
android:launchMode="singleInstance"
我将它放在我的应用程序的主要活动部分下的清单中,然后通知项重用已经在进行中的实例。
答案 3 :(得分:1)
非解决方案对我有用,所以我找到了自己的方式。我的所有活动都来自BaseActivity
。我按照一系列简单的步骤使我的推送通知点击恢复应用程序:
步骤1:记录当前活动的常量:
public static Context currentContext;
第2步:在由onCreate()
onResume()
或BaseActivity
个活动中
currentContext = this;
步骤3:创建通知时Intent
:
Class activity = BaseActivity.commonContext.getClass();
Intent intent = new Intent(this, activity);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//FLAG_UPDATE_CURRENT is important
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
答案 4 :(得分:1)
我发现没有一个答案适用于多任务应用程序。似乎可以理解的是,在多个任务的情况下,Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_SINGLE_TOP的行为并不完全相同。在我的应用程序中,有多个任务根活动。在某些时候,将向用户显示通知,即在其中一个任务中有工作要做。与OP不同,我只需要返回其中一个任务的顶部,而不是特定的活动,这些活动可能隐藏在其中一个任务中。我认为这与提出的问题类似,可能对其他人有用。
我的解决方案包括一个用于跟踪当前任务的静态任务ID,一个用于处理待处理意图的广播接收器,一个新的uses-permission标签,以及一些简单的ActivityManager使用。
std::vector<dog> dogs = get_dogs();
std::vector<std::string> dog_names;
dog_names.reserve(dogs.size());
std::transform(std::begin(dogs), std::end(dogs), std::back_inserter(dog_names), [](auto const& dog) { return dog.name(); });
private static int taskID;
public static void setResumeTask(int tID)
{
Log.e("TaskReturn", "Setting Task ID: " + tID);
taskID = tID;
}
public static PendingIntent getResumeTask(Context appContext)
{
return PendingIntent.getBroadcast(appContext, 0, new Intent(appContext, TaskReturn.class).putExtra(TaskReturn.EXTRA_TASK_ID, taskID), PendingIntent.FLAG_UPDATE_CURRENT);
}
public void onReceive(Context context, Intent intent)
{
Log.e("TaskReturn", "Task Return!");
if (intent.hasExtra(EXTRA_TASK_ID))
{
int taskToStart = intent.getIntExtra(EXTRA_TASK_ID, -1);
Log.e("TaskReturn", "Returning To Task: " + taskToStart);
ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.AppTask> allAppTasks = activityManager.getAppTasks();
for (ActivityManager.AppTask task : allAppTasks)
{
Log.e("TaskReturn", "AllTasks: " + task.getTaskInfo().id + " " + task.getTaskInfo().affiliatedTaskId + " " + task.getTaskInfo().persistentId);
}
activityManager.moveTaskToFront(taskToStart, ActivityManager.MOVE_TASK_WITH_HOME);
}
else
{
Log.e("TaskReturn", "WHERE IS MY EXTRA!?!?!");
//Boo...
}
}
...
<uses-permission android:name="android.permission.REORDER_TASKS"/>
基本上,我们的想法是将对Activity.getTaskId()的调用结果标记为状态。稍后,在创建恢复到该活动任务的通知时,抓取任务ID并将其投入额外的任务ID。然后,将待定意图设置为指向拉出任务ID并启动该任务的广播接收器。
看起来这需要API 21和我使用的调用,我怀疑它可能需要一些额外的错误检查,如果任务已经退出,但它符合我的目的。