24

私はこれを理解したと思っていましたが、この質問についてデバッグした後、通知をキャンセル不可/削除不可にする方法は、自分のアクティビティがまだ onCreated() と onDestroyed() をランダムな順序で取得していることに気付きました。

活動の私のマニフェスト:

<activity
        android:name="***.***.***.*****"
        android:configChanges="orientation|keyboardHidden"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:launchMode="singleTop" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

また、launchmodes singleTask、singleInstance も試しました。

通知の意図コード:

Intent intent = new Intent(context, MyClass.class);
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    //intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    //intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
    //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

ご覧のとおり、関連する可能性があると思われるすべてのフラグを試しましたが、うまくいきませんでした...

これにより、通知がクリックされるたびに AlarmManager を再起動したり、alarmmanager の開始タスクを起動したりするなど、不要なアーティファクトが発生します。これは避けたいです。

助言がありますか?

編集:このような質問がたくさんあることは知っていますが、提供されている解決策はどれもここでうまくいかないようです... :/

Edit2:リクエストにより、ここに私のクラスがあります:

package ***.***.***;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;


public class MyClass extends FragmentActivity {


private static String userName;
String password;
private static Boolean LoggedIn = false;
private static Boolean RunningState = false;
private static Boolean OnlineState = false;
private static String LastReportTime;

private static Boolean isVisible = true;
private static Boolean firstStart = true;

private static TextView onlineTextView;
private static TextView reportTimeTextView;
private static TextView runningStatusTextView;
private static TextView userLoggedInTextView;

private static Context context;

public static final String PREFS_NAME = "Settings";

public static final String NOTIFICATION_RUNNING_OK = "Reporting Active";
public static final String NOTIFICATION_USER_STOPPED = "Reporting Stopped";
public static final String NOTIFICATION_NO_NETWORK = "No Network Connected";
public static final String NOTIFICATION_NO_CONNECTION = "No Connection To Server";

public static final int NOTIFICATION_ID = 10;

public static final int LOGIN_REQUEST_CODE = 1;
public static final int WAKEUP_LOGIN_REQUEST_CODE = 2;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    Log.d("MyClass", "Main onCreate() Called");

    loadVariables();

    com.remobjects.sdk.TypeManager.setPackage("com.remobjects.sdk");
    //if (firstStart)
    //{
        Log.d("MyClass", "Main onCreate() firstStart Called");
        if (RunningState && checkConnection())
        {
           // After runLogin(), onResume() gets called here again immediately
            setLoginCode(LOGIN_REQUEST_CODE);
            runLogin();
        }
        else
            init();
    //}
}

@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
}

@Override
public void onResume()
{
    super.onResume();

    Log.d("MyClass", "Main onResume() Called");
    //firstStart gets set to false during login
    if (!firstStart)
    {
        Log.d("MyClass", "Main onResume() !firstStart Called");
        loadVariables();
        setVisible(true);
        updateUI();
    }
}

@Override
protected void onPause()
{
    super.onPause();
    saveVariables();
    setVisible(false);
}

@Override
protected void onStop()
{
    super.onStop();

    saveVariables();
    setVisible(false);
}

@Override
public void onDestroy()
{
    super.onDestroy();
    //cancelNotification();
    Log.e("MyClass", "onDestroy() called");
    saveVariables();
    setVisible(false);
    //setFirstStart(true);
}


private void loadVariables()
{
    SharedPreferences sharedPrefs = getSharedPreferences(PREFS_NAME, 0);

    userName = sharedPrefs.getString("userName", "");
    RunningState = sharedPrefs.getBoolean("RunningState", true);
    LoggedIn = sharedPrefs.getBoolean("LoggedIn", false);
    OnlineState = sharedPrefs.getBoolean("OnlineState", false);
    LastReportTime = sharedPrefs.getString("LastReportTime", "");

    context = this.getApplicationContext();
}

private static void saveVariables()
{
    SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
    SharedPreferences.Editor editor = settings.edit();

    editor.putString("userName", userName);
    editor.putBoolean("RunningState", RunningState);
    editor.putBoolean("LoggedIn", LoggedIn);
    editor.putBoolean("OnlineState", OnlineState);
    editor.putString("LastReportTime", LastReportTime);

    editor.commit();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_my_class, menu);
    return true;
}

private Boolean checkConnection()
{
    Log.d("MyClass", "checkConnection()");
    ConnectivityManager cnnxManager = (ConnectivityManager) 
            getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo ni = cnnxManager.getActiveNetworkInfo();

    if (ni != null && ni.isAvailable() && ni.isConnected()) 
    {
        OnlineState = true;
        return true;
    }
    OnlineState = false;
    return false;
}

public void runLogin()
{
    Intent intent = new Intent(context, LoginActivity.class);
    startActivityForResult(intent, getLoginCode());
    Log.d("MyClass", "runLogin()");
}

private void init()
{
    Log.d("MyClass", "init()");
    setContentView(R.layout.activity_field_agent);

    onlineTextView = (TextView)findViewById(R.id.onlineStatusTextView);
    reportTimeTextView = (TextView)findViewById(R.id.lastReportTimeTextView);
    runningStatusTextView = (TextView)findViewById(R.id.runningStatusTextView);
    userLoggedInTextView = (TextView)findViewById(R.id.userLoggedInTextView);

    findViewById(R.id.button_online).getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
    findViewById(R.id.button_highRisk).getBackground().setColorFilter(0xFFFFA500, PorterDuff.Mode.MULTIPLY);
    findViewById(R.id.button_alarm).getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);

    setVisible(true);

    updateUI();

    if (RunningState)
    {
        setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES);
        // Here onResume() gets called again
        updateNotificationText(NOTIFICATION_RUNNING_OK);

        Button temp = (Button)findViewById(R.id.button_online);
        temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);
    }
    else
    {
        //cancelAlarmManager();

        updateNotificationText(NOTIFICATION_USER_STOPPED);

        Button temp = (Button)findViewById(R.id.button_offline);
        temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);
    }
}

private void updateUI() 
{
    Log.d("MyClass", "updateUI()");

    updateUserLoggedInStatus(userName);

    updateOnlineStatus(OnlineState);

    updateRunningStatus(RunningState);

    updateReportTimeStatus(LastReportTime);
}

public void offDutyButton_click(View view)
{
    cancelAlarmManager();
    Button temp = (Button)findViewById(R.id.button_offline);
    temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);

    temp = (Button)findViewById(R.id.button_online);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_highRisk);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_alarm);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}

public void onDutyButton_click(View view)
{
    Button temp = (Button)findViewById(R.id.button_online);
    temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);

    temp = (Button)findViewById(R.id.button_offline);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_highRisk);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_alarm);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
    //cancelAlarmManager();
    setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES);
}

public void highRiskButton_click(View view)
{
    Button temp = (Button)findViewById(R.id.button_highRisk);
    temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);

    temp = (Button)findViewById(R.id.button_online);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_offline);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_alarm);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}

public void alarmButton_click(View view)
{
    Button temp = (Button)findViewById(R.id.button_alarm);
    temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);

    temp = (Button)findViewById(R.id.button_online);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_highRisk);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

    temp = (Button)findViewById(R.id.button_offline);
    temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}

public static void setButtonIcon(int inId)
{

}

public static void showToast(String inString, Context context)
{
    Toast.makeText(context, inString.toString(), Toast.LENGTH_SHORT).show();
}

public static void updateOnlineStatus(Boolean inStatus)
{
    if (isVisible)
    {
        if (inStatus)
            onlineTextView.setText("Online");
        else
            onlineTextView.setText("Offline");
    }
}

public static void updateReportTimeStatus(String inString)
{
    if (isVisible)
        reportTimeTextView.setText(inString);
}

public static void updateRunningStatus(Boolean inStatus)
{
    if (isVisible)
    {
        if (inStatus)
            runningStatusTextView.setText("Reporting");
        else
            runningStatusTextView.setText("Not Reporting");
    }
}

public static void updateUserLoggedInStatus(String inString)
{
    if (isVisible)
        userLoggedInTextView.setText(inString);
}


//
//
// Getters and Setters
//
//
public static void setLoggedIn(Boolean inBool)
{
    LoggedIn = inBool;
}

public static Boolean getLoggedIn()
{
    return LoggedIn;
}

public static void setRunningState(Boolean inBool)
{
    RunningState = inBool;
}

public static Boolean getRunningState()
{
    return RunningState;
}

public static void setVisible(Boolean inBool)
{
    isVisible = inBool;
}

public static Boolean getVisible()
{
    return isVisible;
}

public static void setUsername(String inString)
{
    userName = inString;
}

public static String getUsername()
{
    return userName;
}

public static void setLastReportTime(String inString)
{
    LastReportTime = inString;
}

public static String getLastReportTime()
{
    return LastReportTime;
}

public static Context getAppContext()
{
    return MyClass.context;
}

public static void setLoginCode(int code)
{
    SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
    SharedPreferences.Editor editor = settings.edit();

    editor.putInt("LoginCode", code);

    editor.commit();
}

public static int getLoginCode()
{
    SharedPreferences sharedPrefs = context.getSharedPreferences(PREFS_NAME, 0);

    return sharedPrefs.getInt("LoginCode", 1);
}

public static void setFirstStart(Boolean inBool)
{
    firstStart = inBool;
}

public static Boolean getFirstStart()
{
    return firstStart;
}

//
//
//
//
//
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  switch(requestCode) {
    case (LOGIN_REQUEST_CODE) : {
      if (resultCode == Activity.RESULT_OK) {
        LoggedIn = data.getBooleanExtra("LoggedIn", false);
        userName = data.getStringExtra("Username");

        init();
      }
      break;
    }
    case (WAKEUP_LOGIN_REQUEST_CODE) : {
        if (resultCode == Activity.RESULT_OK) {
          LoggedIn = data.getBooleanExtra("LoggedIn", false);
          userName = data.getStringExtra("Username");

          cancelAlarmManager();
          setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES);
        }
        break;
    }
  }
}

//
//
// AlarmManager
//
//

public static void setupAlarmManager(long interval)
{
    AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent alarmIntent = new Intent(context, LaunchReceiver.class); 
    PendingIntent pendingAlarmIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, alarmIntent, 0);
    alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, interval,  pendingAlarmIntent);

    RunningState = true;
    updateRunningStatus(RunningState);

    updateNotificationText(NOTIFICATION_RUNNING_OK);

    Log.d("MyClass", "AlarmManager Started");
}


public static void cancelAlarmManager()
{
    Intent intent = new Intent(context.getApplicationContext(), LaunchReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    alarmMgr.cancel(pendingIntent);

    RunningState = false;
    updateRunningStatus(RunningState);

    updateNotificationText(NOTIFICATION_USER_STOPPED);

    Log.d("MyClass", "AlarmManager Stopped");

    Intent serviceIntent = new Intent(context, MonitorService.class);
    context.stopService(serviceIntent);
    Log.d("MyClass", "Stopping MonitorService");
}



//
//
// Notification
//
//

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void createNotification()
{
    NotificationManager notificationManager = (NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                            .setContentTitle("blablabla")
                            .setContentText("Getting Status")
                            .setSmallIcon(R.drawable.ic_launcher)
                            .setOngoing(true)
                            .setAutoCancel(false);

    Intent intent = new Intent(context, MyClass.class);
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    //intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    //intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
    //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(MyClass.class);
    stackBuilder.addNextIntent(intent);

    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT);

    builder.setContentIntent(pendingIntent);

    /*Notification noti = builder.build();
    noti.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;*/

    notificationManager.notify(NOTIFICATION_ID, builder.build());
}

public static void updateNotificationText(String inString)
{
    NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                                            .setContentText(inString)
                                            .setContentTitle("blablabla")
                                            .setSmallIcon(R.drawable.ic_launcher)
                                            .setOngoing(true)
                                            .setAutoCancel(false);

    Intent intent = new Intent(context, MyClass.class);
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(MyClass.class);
    stackBuilder.addNextIntent(intent);

    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT);

    builder.setContentIntent(pendingIntent);

    /*Notification noti = builder.build();
    noti.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;*/

    notificationManager.notify(NOTIFICATION_ID, builder.build());
}

public static void cancelNotification()
{
    NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.cancel(NOTIFICATION_ID);
}
}

コメントで述べたように、loginActivity を開始した後、ここで onResume() がすぐに再度呼び出されます。alarmManager を起動した後も同じです。

また、alarmManager がカチカチ鳴るたびに、アプリがフォアグラウンドに移動するようです。それを回避する方法はありますか?

4

5 に答える 5

39

この問題は、通知コードの次の行によって引き起こされたようです (通知に関する Android のガイドから直接取得したもの:

TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(FieldAgent.class);
    stackBuilder.addNextIntent(intent);

    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT);

このような通常の保留中の意図に置き換えると、解決しました:

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

完全な例

Intent intent = new Intent(getApplicationContext(), myactivity.class);
PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), intent, 0);

Notification myNotification  = new Notification.Builder(getApplicationContext())
                        .setContentTitle("Title")
                        .setContentText("Some text....")
                        .setSmallIcon(R.drawable.myicon)
                        .setContentIntent(pIntent)
                        .setAutoCancel(true).build();


NotificationManager notificationManager =
                        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

notificationManager.notify(0, myNotification);
于 2013-06-04T13:38:12.503 に答える
7

私の場合、CeeRo の回答は機能しましたが、奇妙な方法でした。電話を再起動する必要がありました。:)

于 2015-05-14T09:30:16.563 に答える
6

私のケースがあなたを好きかどうかはわかりません。私はあなたとして意図を作成しようとしました。pageviewer + fragment を使用しています。私の場合、通知メッセージをクリックしてアプリに移動し、次にメインに移動してから、アプリを再度起動し、アクティビティを再作成します(クラスフラグメントのこのコード)

Intent intent = new Intent(getActivity(),MainActivity.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent =  PendingIntent.getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

これで問題ありません。次のコードに変更します。

Intent intent = getActivity().getIntent();
PendingIntent pendingIntent =  PendingIntent.getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

この助けを願っています^_^

于 2013-08-08T10:24:09.937 に答える
0

アクティビティで onBackPressed をオーバーライドしましたか? onBackPressed をオーバーライドしない場合、Android のデフォルトは Activity を破棄 (finish()) することだと思います。したがって、おそらく戻る場合、通知はアクティビティが既に存在するかどうかを確認し、何も見つけずに新しいアクティビティを作成します。

于 2013-06-03T13:55:13.220 に答える