内容简介:在运行代码,点击
在 MainActivity 中增加点击事件,用来启动 NotifyService 和延迟2秒销毁 MainActivity ,如下面代码所示
Intent intent = new Intent(MainActivity.this, NotifyService.class);
startService(intent);
tvTips.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 2000L);
复制代码
NotifyService 类继承 IntentService ,并在 onHandleIntent() 方法类处理展示通知栏的逻辑,如下面代码所示
private void showNotification() {
Notification notification;
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//pendingIntent生成规则
Intent notifyIntent = new Intent();
notifyIntent.setClass(this, NotifyActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("0", "notify",
NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(this, "0")
.setAutoCancel(true)
.setContentTitle(getString(R.string.app_name))
.setContentText("xxx")
.setOnlyAlertOnce(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent);
notification = builder.build();
} else {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("xxx")
.setAutoCancel(true)
.setWhen(System.currentTimeMillis())
.setOnlyAlertOnce(true)
.setContentTitle(getString(R.string.app_name))
.setContentIntent(pendingIntent);
notification = builder.build();
}
manager.notify(0, notification);
}
复制代码
运行代码,点击 启动通知栏 按钮,此时会创建一个通知栏,并且2秒后,主页自动关闭。然后在点击 通知栏 ,进入到 通知栏页面 ,点击返回按钮时,发下APP没有回到主页面,而是回到了Launcher主页面。如下面截图所示
所以用 PendingIntent.getActivity 方式打开通知栏,就会出现上面所描述的问题。为了解决这问题,提供了一下几种方式。
用PendingIntent.getActivities创建通知栏
处理逻辑基本上跟上面一致,只需替换 pendingIntent生成规则 那部分代码,需替换的代码如下面所示
Intent notifyIntent = new Intent();
Intent mainIntent = new Intent();
notifyIntent.setClass(this, NotifyActivity.class);
mainIntent.setClass(this, MainActivity.class);
//需要注意这里的顺序
Intent[] intents = new Intent[]{mainIntent, notifyIntent};
PendingIntent pendingIntent = PendingIntent.
getActivities(this, 0, intents, PendingIntent.FLAG_UPDATE_CURRENT);
复制代码
运行代码,如下面截图所示
此方法适用于 MainActivity 和 NotifyActivity 在同一个moudle的情况。如果不在同一个moudle又该如何处理呢?接着往下看。
用TaskStackBuilder创建通知栏
替换 pendingIntent生成规则 那部分代码,需替换的代码如下面所示
Intent notifyIntent = new Intent(); notifyIntent.setClass(this, NotifyActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(NotifyActivity.class); stackBuilder.addNextIntent(notifyIntent); PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 复制代码
除了替换 pendingIntent生成规则 之外,还需要修改 AndroidManifest.xml 内的代码,为 NotifyActivity 指定 parentActivityName 属性,如下面代码所示
<activity android:name=".NotifyActivity"
android:parentActivityName=".MainActivity"/>
复制代码
该属性是在Android 4.1(API level 16)引入的,此处的名称必须与为相应 <activity> 元素的 android:name 属性指定的类名称一致,以确定当用户按下返回按钮时应该启动哪一个 Activity 。
运行代码,效果如图2所示
此方法可以适用于 Activity 在不同moudle的情况。
但是,当主页 MainActivity (这里用A代表,方便后面描述)的 launchMode 设置为 singleTask 时,当主页 A 存在时,并且还打开了其他页面'OtherActivity'(B),目前Activity的栈的顺序是 A、B 。当打开用 PendingIntent.getActivities 和 TaskStackBuilder 两种方式创建的通知栏,页面跳转到 NotifyActivity (C),并且一直按返回键,退栈的顺序是 C、A、Launcher , B 却没在栈内了,见 图3 。具体原因是,当打开通知栏是,栈的顺序是 A、B、A ,由于 A 的 launchMode 是 singleTask ,此时会删除 B ,当整个通知栏操作全部完成时,Activity的栈的顺序是 A、C ,所以会出现上面描述的现象。如果要满足退栈顺序是 C、B、A、Launcher 该怎么实现?
用PendingIntent.getActivity创建通知栏,本地维护Activity栈
- 首先需要创建一个Activity管理类
ActivityManager,来维护Activity栈,如下面代码所示
public class ActivityManager {
private static final byte[] sLock = new byte[0];
private final Stack<Activity> mActivityStack = new Stack<>();
private static ActivityManager sInstance;
public static ActivityManager getInstance() {
if (sInstance == null) {
synchronized (sLock) {
if (sInstance == null) {
sInstance = new ActivityManager();
}
}
}
return sInstance;
}
private ActivityManager() {
}
/**
* activity入栈
*/
public void addActivity(Activity activity) {
mActivityStack.add(activity);
}
/**
* activity出栈
*/
public void removeActivity(Activity activity) {
mActivityStack.remove(activity);
}
/**
* 当栈的个数为1的时候,判断cls是否在栈内
*/
public boolean currentActivity(Class<?> cls) {
if (mActivityStack.size() != 1) {
return true;
}
for (Activity activity : mActivityStack) {
if (activity.getClass().equals(cls)) {
return true;
}
}
return false;
}
}
复制代码
- 其次创建一个
Activity的基类BaseActivity,所有Activity页面需要继承这个基类,并且分别在onCreate和onDestroy方法中分别实现Activity的入栈和出栈操作,并且重写返回事件,如下面代码所示
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityManager.getInstance().addActivity(this);
}
@Override
public void onBackPressed() {
super.onBackPressed();
if (!ActivityManager.getInstance().currentActivity(MainActivity.class)) {
Intent intent = new Intent(BaseActivity.this, MainActivity.class);
startActivity(intent);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityManager.getInstance().removeActivity(this);
}
}
复制代码
运行代码,如下面截图所示
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 回到未来:永恒的lisp
- Istiod——回到单体的理由
- [译] Istiod:回到单体的理由
- 用关系型 NoSQL 回到未来
- 回到基础:如何用原生 DOM API 生成表格
- 从Rails到Clojure再到Java,最后回到Rails
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Text Processing in Python
David Mertz / Addison-Wesley Professional / 2003-6-12 / USD 54.99
Text Processing in Python describes techniques for manipulation of text using the Python programming language. At the broadest level, text processing is simply taking textual information and doing som......一起来看看 《Text Processing in Python》 这本书的介绍吧!
图片转BASE64编码
在线图片转Base64编码工具
HSV CMYK 转换工具
HSV CMYK互换工具