GCM 如何检测应用程序是不是打开,如果是,则弹出警报框,而不是正常的通知流程?
Posted
技术标签:
【中文标题】GCM 如何检测应用程序是不是打开,如果是,则弹出警报框,而不是正常的通知流程?【英文标题】:GCM How do I detect if app is open and if so pop up an alert box, instead of normal notification flow?GCM 如何检测应用程序是否打开,如果是,则弹出警报框,而不是正常的通知流程? 【发布时间】:2014-05-09 07:32:53 【问题描述】:我有一个应用程序,我想在其中构建 2 个不同的流程:
1.a 应用在任何活动中都打开1.b 应用程序显示是一个警报框,用户可以在其中选择转到有关通知的活动或停留在当前活动上。
2.a 应用在后台运行
2.b 通知栏中的通知,启动与通知相关的活动。我目前有流程 2 工作,但不知道如何让流程 1 工作。这是一些代码:
在 GcmIntentService 中:
@Override
protected void onHandleIntent(Intent intent)
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM will be
* extended in the future with new message types, just ignore any message types you're
* not interested in, or that you don't recognize.
*/
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType))
Log.e("GCM", "Send error: " + extras.toString());
else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType))
Log.e("GCM", "Deleted messages on server: " + extras.toString());
// If it's a regular GCM message, do some work.
else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType))
Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
// Post notification of received message.
sendNotification(extras);
Log.i(TAG, "Received: " + extras.toString());
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(Bundle extras)
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
String message = extras.getString("message");
Intent openIntent = new Intent(this, HomeActivity.class);
if (extras != null)
if (extras.containsKey("tipid"))
openIntent.putExtra("tipid", extras.getString("tipid"));
else if (extras.containsKey("discussionid"))
openIntent.putExtra("discussionid", extras.getString("discussionid"));
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
openIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("StadseBoeren")
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.setContentText(message);
mBuilder.setContentIntent(contentIntent)
.setAutoCancel(true);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
GcmBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver
@Override
public void onReceive(Context context, Intent intent)
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
HomeActivity onCreate:
Bundle extras = intent.getExtras();
if (extras != null)
if (extras.containsKey("tipid"))
pendingObjectId = extras.getString("tipid");
modelFlag = ModelFlag.TIP;
else if (extras.containsKey("discussionid"))
pendingObjectId = extras.getString("discussionid");
modelFlag = ModelFlag.DISCUSSION;
【问题讨论】:
【参考方案1】:创建一个类扩展 Application 并实现 ActivityLifecycleCallbacks 并根据 on pause 和 onResume 更新一个公共布尔值。
在收到推送时检查此布尔值并按照您的要求执行。
希望对你有帮助
public class TestApplication extends Application implements ActivityLifecycleCallbacks
boolean applicationOnPause = false;
@Override
public void onCreate()
super.onCreate();
registerActivityLifecycleCallbacks(this);
@Override
public void onActivityCreated(Activity arg0, Bundle arg1)
Log.e("","onActivityCreated");
@Override
public void onActivityDestroyed(Activity activity)
Log.e("","onActivityDestroyed ");
@Override
public void onActivityPaused(Activity activity)
applicationOnPause = true;
Log.e("","onActivityPaused "+activity.getClass());
@Override
public void onActivityResumed(Activity activity)
applicationOnPause = false;
Log.e("","onActivityResumed "+activity.getClass());
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState)
Log.e("","onActivitySaveInstanceState");
@Override
public void onActivityStarted(Activity activity)
Log.e("","onActivityStarted");
@Override
public void onActivityStopped(Activity activity)
Log.e("","onActivityStopped");
【讨论】:
我认为这应该能够工作,但我需要在所有活动中实施这一点,对吧? 无需在所有活动中实现这一点,只需在应用程序类上执行即可。见编辑部分。每次打开关闭(暂停)的活动时都会收到呼叫 请注意这是在 ApI 级别 14 中实现的【参考方案2】:我会像这样写另一个BroadcastReceiver
:
public class MainActivityBroadcastReceiver extends BroadcastReceiver
public MainActivityBroadcastReceiver(Activity mainActivity)
@Override
public void onReceive(Context context, Intent intent)
Toast toast = Toast.makeText(context, "hola", Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
然后在MainActivity
中,我会覆盖这些方法,然后我没有收到通知,所以我拦截了 `Intent~ 并中止了另一个广播:
@Override
protected void onPause()
unregisterReceiver(mainActivityBroadcastReceiver);
super.onPause();
@Override
public void onResume()
IntentFilter filter = new IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.setPriority(1);
registerReceiver(mainActivityBroadcastReceiver, filter);
super.onResume();
【讨论】:
【参考方案3】:在我的代码中,我有 public static ArrayList<Activity> activity_stack
每个活动都在 oncreate 中添加并在 ondestroy 方法中删除。我在 GcmBroadcastReceiver 中检查了这个堆栈。不知道有没有好办法。
【讨论】:
【参考方案4】:我刚刚找到的解决方案确实需要 GET_TASK 权限:
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager
.getRunningTasks(Integer.MAX_VALUE);
boolean isActivityFound = false;
if (services.get(0).topActivity.getPackageName().toString()
.equalsIgnoreCase(getApplicationContext().getPackageName().toString()))
isActivityFound = true;
Log.d("GCM", "Activity open: "+isActivityFound);
更新
为了启动警报框(这在此处不可能),我创建了一个自定义警报框并让它使用警报框作为主题。这是 AndroidManifest.xml 中的活动:
<activity
android:name="nl.raakict.android.stadseboeren.NotificationAlertActivity"
android:label="@string/title_activity_notification_alert"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Dialog" >
还有自定义活动:
public class NotificationAlertActivity extends Activity implements
Observer, OnClickListener
private String pendingObjectId;
private ModelFlag modelFlag;
private Database db;
private ArrayList<Discussion> discussions;
private ArrayList<Tip> tips;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_alert);
findViewById(R.id.button_yes).setOnClickListener(this);
findViewById(R.id.button_no).setOnClickListener(this);
我用这个位更新了 onHandleIntent:
if (isActivityFound)
Intent dialogIntent = new Intent(getBaseContext(),
NotificationAlertActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
【讨论】:
以上是关于GCM 如何检测应用程序是不是打开,如果是,则弹出警报框,而不是正常的通知流程?的主要内容,如果未能解决你的问题,请参考以下文章
如果在textbook中输入小数,按ctrl结束,则弹出提示窗口,用VB编码怎么写?