簡體   English   中英

如何使通知意圖恢復而不是制定新的意圖?

[英]How to make notification intent resume rather than making a new intent?

我在這里有一個簡單的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...");        
}

我們的想法是,人們可以遠離此活動,並通過下拉菜單並選擇它,從他們想要的任何屏幕再次快速訪問它。

請選擇此選項。

但是,當按下通知時,它會啟動活動的新實例。

這將默認發生。

我需要更改什么才能看到活動是否尚未被銷毀,我可以回調用該實例(恢復它),因此不需要再次加載它,也不需要在我的堆棧中添加其他活動。

擺脫FLAG_ACTIVITY_NEW_TASK 添加notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - 請參閱此示例項目

Context context = getApplicationContext();

請不要這樣做。 只需將您的Activity用作Context

這是我顯示通知的方法。 我希望它對你有所幫助。

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());
}

以防其他人遇到同樣的困難....

我嘗試了上面的所有代碼但沒有成功 - 通知項目繼續啟動我的應用程序的全新實例,即使其中一個已經運行。 (我只想在任何時候有一個實例可用。)最后注意到另一個線程( https://stackoverflow.com/a/20724199/4307281 ),它在清單中需要一個簡單的附加條目:

android:launchMode="singleInstance"

我將它放在我的應用程序的主要活動部分下的清單中,然后通知項重用已經在進行中的實例。

沒有解決方案適合我,所以我找到了自己的方式。 我的所有活動都是從BaseActivity擴展而來的。 我按照一系列簡單的步驟使我的推送通知點擊恢復應用程序:

第1步:記錄當前活動的常量:

public static Context currentContext;

第2步:在BaseActivity擴展的活動的onCreate()onResume()

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);

我發現沒有一個答案適用於多任務應用程序。 似乎可以理解的是,在多個任務的情況下,Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_SINGLE_TOP的行為並不完全相同。 在我的應用程序中,有多個任務根活動。 在某些時候,將向用戶顯示通知,即在其中一個任務中有工作要做。 與OP不同,我只需要返回其中一個任務的頂部,而不是特定的活動,這些活動可能隱藏在其中一個任務中。 我認為這與提出的問題類似,可能對其他人有用。

我的解決方案包括一個用於跟蹤當前任務的靜態任務id,一個用於處理待處理意圖的廣播接收器,一個新的uses-permission標簽,以及一些簡單的ActivityManager使用。

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"/>

...

<receiver android:name=".TaskReturn"/>

基本上,我們的想法是將對Activity.getTaskId()的調用結果標記為狀態。 稍后,在創建恢復到該活動任務的通知時,抓取任務ID並將其投入額外的任務ID。 然后,將待定意圖設置為指向拉出任務ID並啟動該任務的廣播接收器。

看起來這需要API 21和我使用的調用,我懷疑它可能需要一些額外的錯誤檢查,如果任務已經退出,但它符合我的目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM