3

私は 4 つのアクティビティを含むアプリケーションを持っています。アプリケーション内で、ユーザーは常に 4 つのアクティビティをナビゲートしていることに気付くでしょう。アプリケーションにはバックグラウンドで進行中のサービスもあり、サービスはステータスバー通知を表示し、通知に表示されるコンテンツの変更をリッスンします。

現在、サービスは、ユーザーが通知の表示を必要とするアクションを開始するたびに通知を表示するため、アプリケーションを使用している場合でも通知が表示されます。望ましいシナリオは、ユーザーがアプリケーションから移動したときにのみ通知を表示することです。

次のようなライフサイクルメソッドをオーバーライドしようとしました:

    @Override
protected void onPause() {  
    Intent intent = new Intent();
    intent.setAction(MyService.ACTION_DISPLAY_PENDING_NOTIFICATION);
    sendBroadcast(intent);
    super.onPause();
}

@Override
protected void onResume() { 
    super.onResume();
    Intent intent = new Intent();
    intent.setAction(MyService.ACTION_CANCEL_NOTIFICATION);
    sendBroadcast(intent);      
}

サービスは次のようになります。

@Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (action.equals(ACTION_DISPLAY_PENDING_NOTIFICATION)) {
            showNotification();
        }

        else if (action.equals(ACTION_CANCEL_NOTIFICATION)) {
            mNotificationManager.cancel(mNotId);
        }
    }

これは、動作します。ただし、ユーザーがアクティビティから移動するたびにインテントが送信されるため、ユーザーが 4 つのアクティビティを移動すると、望ましくない動作とわずかなパフォーマンス ヒットが発生します。サービスは、アクティビティ A からアクティビティ B、または 4 つのアクティビティ内の任意の組み合わせに移動する場合でも、通知を表示しようとします。

新しいアクティビティ B が開始されると、 onResume 中にmNotificationManager.cancel (mNotifId) が呼び出されるため、通知はすぐにキャンセルされますが、アクティビティ A を離れるときにサービスがそうするように指示されたため、通知が作成され、ほんの一瞬だけ表示されました。この通知を不必要に構築して表示するのではなく、それが私が対処したい動作です。

ユーザーがいつアクティビティを別のアプリケーション、つまりホームページなどに残しているかを知る方法はありますか? しかし、アプリケーション自体の中ではありませんか?

編集

明確にするために、アクティビティが onPause メソッド中にチェックする必要があることが 2 つあります。

a) フォアグラウンドで以前のアクティビティはありますか? なんで?ユーザーは [戻る] を押してアクティビティの外に移動できるため、スタックの最後のアクティビティが表示されることを意味します。これを確認するには、DennisDrew からの回答が機能します。次のように確認できます。

if(!ForegroundHelper.activityExistsInForeground()){
//show your notification
}

しかし、それがユーザーがアクティビティから移動できる唯一の方法ではありません。ユーザーは HomeKey を押すこともできます。その場合、activityExistsInForeground()true または false のどちらに評価されても、通知が表示されます。

b) ユーザーはアプリケーション内の別のアクティビティに移動しますか? たとえば、ユーザーがアクティビティ A を使用していて、現時点では A がフォアグラウンドで唯一のアクティビティであり、ユーザーがアクティビティ B を起動する UI 要素をクリックすると、activityExistsInForeground()false と評価されたにもかかわらず、ユーザーはアプリケーションを離れ、新しいインスタンスを起動しています以前は外界にいなかった活動の。

private boolean launchingNewActivity = falseデフォルトなどのフラグを追加しようとしましたがtrue、たとえば、リストビューのアイテムをクリックしている間など、別のアクティビティに行くことがわかっているときにフラグを設定しました。

litview.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            launchingNewActivity = true
            startActivity2(arg2);
        }           
    });

次に、onPause 中にそれを確認します。

@Override
protected void onPause() {
    if(!ForegroundHelper.activityExistsInForeground() && launchingNewActivity){
    //show your notification        
}

しかし、これを行うと、通知が表示されることはありません。どういうわけか、二重チェックは常にデフォルトで false になります。

4

2 に答える 2

3

シングルトン参照を使用した場合はどうなりますか? 次のようなクラスを作成できます。

public static class ForegroundHelper {
    public static boolean[] activityStates = new boolean{false, false, false, false};
    public static final int ACTIVITY_A = 0;
    public static final int ACTIVITY_B = 1;
    public static final int ACTIVITY_C = 2;
    public static final int ACTIVITY_D = 3;

    public static boolean activityExistsInForeground(){
        for(boolean b : activityStates){
            if(b)
                return true;
        }

        return false;
    }
}

次に、各アクティビティの onResume() で次のことを行います。

//For your first activity (Activity A)
ForegroundHelper.activityStates[ForegroundHelper.ACTIVITY_A] = true;

そして、各アクティビティの onPause() で次のことを行います。

ForegroundHelper.activityStates[ForegroundHelper.ACTIVITY_A] = false;

そして、各アクティビティの onStop() で次のことを行います。

if(!ForegroundHelper.activityExistsInForeground()){
    //show your notification
}

ちなみに、私はこのようなことをしたことがないので、コーディングしたとおりに機能するかどうかはわかりません...しかし、これが役立つかどうか教えてください.

于 2013-02-06T17:01:47.743 に答える
2

そのために私がしたことは、アプリケーション クラスを拡張し、次のように各 onResume /onPause メソッドに設定する「topActivity」を保持することです。

public class myApp extends Application{

   private Activity topActivity;
}

今、それぞれの活動で

@Override
protected void onResume() {

((myApp) getApplication()).setOnTopActivity(this);
}

@Override
    protected void onPause() {
        ((myApp) getApplication()).setOnTopActivity(null);
        super.onPause();
    }

このように、アプリが表示されていない場合、topActivity は null です。したがって、通知を表示する前に、 topActivity==nullかどうかを確認してください。そうである場合、アプリはフォアグラウンドにありません。通知を表示できます。

アプリケーションクラスにアクセスできない場合は、いつでもこの値を静的な方法で保存できます:)

于 2013-02-06T22:38:24.877 に答える