私はこれを理解したと思っていましたが、この質問についてデバッグした後、通知をキャンセル不可/削除不可にする方法は、自分のアクティビティがまだ 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 がカチカチ鳴るたびに、アプリがフォアグラウンドに移動するようです。それを回避する方法はありますか?