- 浏览: 1613216 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (603)
- T_java (145)
- T_script&ASP (51)
- T_C/C++ (25)
- T_PowerBuilder (11)
- T_Database (53)
- T_odoo (7)
- T_应用服务器 (50)
- T_专_条形码 (6)
- T_专_负载均衡器 (4)
- T_操作系统 (94)
- T_信息安全 (41)
- T_专_搜索引擎 (14)
- T_L_PHP (58)
- T_L_Delphi (18)
- T_L_.NET、C#、VisualStudio (25)
- T_L_Objective-C (6)
- T_移动开发 (53)
- T_网络 (109)
- T_大数据 (2)
- T_嵌入式 (2)
- T_小众技术 (24)
- T_未分类 (58)
- L_旅游印记 (1)
- L_生活随笔 (48)
- L_中国文化 (18)
- L_户外与生存 (0)
最新评论
-
csbean4004:
不知道哪传来得恶习,发帖子不好好发,故意弄错一些东西,很讨厌
让HTML5支持后置摄像头 -
withthewind:
终于找到一个可以用的了。。。
如何用VBA取得Word文档中的标题前面的序号 -
busbby:
兄弟,无法下载,说文件不完整
一个好用的Outlook ost格式文件转pst文件的工具 -
yijavakevin:
密码啊~解压密码多少?
一个二维条形码组件 -
vipbooks:
你给的那个链接根本无法下载,跳到官网看了下最新版12M,但点下 ...
十步以内完成精细web打印
本文原源:http://www.cnblogs.com/hanyonglu/archive/2012/04/15/2450551.html
====================================================================
本文演示如何在Android中实现程序前后台切换效果。
在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识。
我们都知道,一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的,比如说,想要给用户展示一个地图的信息,现在已经有一个Activity可以做这件事情,那么现在你的Activity需要做的就是将请求信息放进一个Intent对象里,并且将这个Intent对象传递给startActivity(),那么地图就可显示出来了,但用户按下Back键之后,你的Activity又重新出现在屏幕上。
对用户来讲,显示地图的Activity和你的Activity好像在一个应用程序中的,虽然是他们是定义在其他的应用程序中并且运行在那个应有进程中。Android将你的Activity和借用的那个Activity被放进一个Task中以维持用户的体验。那么Task是以栈的形式组织起来一组相互关联的Activity,栈中底部的Activity就是开辟这个Task的,通常是用户在应用程序启动器中选择的Activity。栈的顶部的Activity是当前正在运行的Activity--用户正在交互操作的Activity。
当一个Activity启动另一个Activity时,新启动的Activity被压进栈中,成为正在运行的Activity。旧的Activity仍然在栈中。当用户按下BACK键之后,正在运行的Activity弹出栈,旧的Activity恢复成为运行的Activity。栈中包含对象,因此如果一个任务中开启了同一个Activity子类的的多个对象——例如,多个地图浏览器——则栈对每一个实例都有一个单独的入口。栈中的Activity不会被重新排序,只会被、弹出。Task是一组Activity实例组成的栈,不是在manifest文件里的某个类或是元素,所以无法设定一个Task的属性而不管它的Activity,一个Task的所有属性值是在底部的Activity里设置的,这就需要用于Affinity。关于Affinity这里不再详述,大家可以查询文档。
一个Task里的所有Activity作为一个整体运转。整个Task(整个Activity堆栈)可以被推到前台或被推到后台。假设一个正在运行的Task中有四个Activity——正在运行的Activity下面有三个Activity,这时用户按下HOME键,回到应有程序启动器然后运行新的应用程序(实际上是运行了一个新的Task),那么当前的Task就退到了后台,新开启的应用程序的root Activity此时就显示出来了,一段时间后,用户又回到应用程序器,又重新选择了之前的那个应用程序(先前的那个Task),那么先前的那个Task此时又回到了前台了,当用户按下BACK键时,屏幕不是显示刚刚离开的那个新开启的那个应用程序的Activity,而是被除回到前台的那个Task的栈顶Activity,将这个Task的下一个Activity显示出来。 上述便是Activity和Task一般的行为,但是这个行为的几乎所有方面都是可以修改的。Activity和Task的关系,以及Task中Activity的行为,是受启动该Activity的Intent对象的标识和在manifest文件中的Activity的<Activity>元素的属性共同影响的。
以上是关于Activity和Task的描述。
在开发Android项目时,用户难免会进行程序切换,在切换过程中,程序将进入后台运行,需要用时再通过任务管理器或是重新点击程序或是通过点击信息通知栏中的图标返回原来的界面。这种效果类似于腾讯QQ的效果,打开QQ后显示主界面,在使用其他的程序时,QQ将以图标的形式显示在信息通知栏里,如果再用到QQ时再点击信息通知栏中的图标显示QQ主界面。
先看下本示例实现效果图:
在上图第二个图中,我们点击时将会返回到的原来的Activity中。
当我们的程序进入后台运作时,在我们的模拟器顶部将以图标形式出现,如下图:
对于这种效果一般的做法是在Activity中的onStop()方法中编写相应代码,因为当Activity进入后台时将会调用onStop()方法,我们可以在onStop()方法以Notification形式显示程序图标及信息,其中代码如下所示:
以上的showNotification()方法就是Notification。然后点击信息通知栏的Notification后再返回到原来的Activity。当然,我们也可以捕捉HOME键,在用户按下HOME键时显示Notification, 以下是代码示例:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
// 按下HOME键
if(keyCode == KeyEvent.KEYCODE_HOME){
// 显示Notification
notification = new NotificationExtend(this);
notification.showNotification();
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Color;
/**
* Notification扩展类
* @Description: Notification扩展类
* @File: NotificationExtend.java
* @Package com.test.background
* @Author Hanyonglu
* @Date 2012-4-13 下午02:00:44
* @Version V1.0
*/
public class NotificationExtend {
private Activity context;
public NotificationExtend(Activity context) {
// TODO Auto-generated constructor stub
this.context = context;
}
// 显示Notification
public void showNotification() {
// 创建一个NotificationManager的引用
NotificationManager notificationManager = (
NotificationManager)context.getSystemService(
android.content.Context.NOTIFICATION_SERVICE);
// 定义Notification的各种属性
Notification notification = new Notification(
R.drawable.icon,"阅读器",
System.currentTimeMillis());
// 将此通知放到通知栏的"Ongoing"即"正在运行"组中
notification.flags |= Notification.FLAG_ONGOING_EVENT;
// 表明在点击了通知栏中的"清除通知"后,此通知自动清除。
notification.flags |= Notification.FLAG_AUTO_CANCEL
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults = Notification.DEFAULT_LIGHTS;
notification.ledARGB = Color.BLUE;
notification.ledOnMS = 5000;
// 设置通知的事件消息
CharSequence contentTitle = "阅读器显示信息"; // 通知栏标题
CharSequence contentText = "推送信息显示,请查看……"; // 通知栏内容
Intent notificationIntent = new Intent(context,context.getClass());
// 取消通知
public void cancelNotification(){
NotificationManager notificationManager = (
NotificationManager) context.getSystemService(
android.content.Context.NOTIFICATION_SERVICE);
notificationManager.cancel(0);
}
}
在使用FLAG_ACTIVITY_NEW_TASK控制标识时也会出现不会返回到原Activity的现象。如果该标识使一个Activity开始了一个新的Task,然后当用户按了HOME键离开这个Activity,在用户按下BACK键时将无法再返回到原Activity。一些应用(例如Notification)总是在一个新的Task里打开Activity,而从来不在自己的Task中打开,所以它们总是将包含FLAG_ACTIVITY_NEW_TASK的Intent传递给startActivity()。所以如果有一个可以被其他的东西以这个控制标志调用的Activity,请注意让应用程序有独立的回到原Activity的方法。 代码如下:
android:launchMode="singleTask"></activity>
<activity>下的launchMode属性可以设置四种启动方式:
standard (默认模式)
singleTop
singleTask
singleInstance
这四个模式有以下的几个不同点:
1. 响应Intent时Activity将被装入哪个task。
对于standard和singleTop模式,由产生该Intent(调用startActivity())的task持有该Activity——除非Intent对象里含有FLAG_ACTIVITY_NEW_TASK标志,那么就会寻找一个新的task。
相反的,singTask和singleInstance模式,总是标志Activity为task的root Activity,开启这样的活动会新建一个task,而不是装入某个正在运行的任务。
2. 一个Activity是否可以有多个实例。
一个standard或者singleTop属性的Activity可以实例化多次,他们可以属于多个不同的task,而且一个task也可以含有相同Activity的多个实例。
相反的,singleTask或者singleInstance属性的Activity只能有一个实例(单例),因为这些Activity是位于task的底部,这种限制意味着同一设备的同一时刻该task只能有一
3. 实例是否能允许在它的task里有其他的Activity。
一个singleInstance属性的Activity是它所在的task里仅有的一个Activity,如果他启动了另一个Activity,那个Activity会被加载进一个不同的task而无视它的启动模式——就如Intent里有FLAG_ACTIVITY_NEW_TASK标识一样。在其他的方面,singleInstance和singleTask一样的。
其他三个模式允许有多个Activity在一个task里,一个singleTask属性的Activity总是一个task里的root Activity,但是他可以启动另外的Activity并且将这个新的Activity装进同一个task里,standard和singleTop属性的Activity可以出现在task的任何位置。
4. 是否创建一个新的Activity实例来处理一个新的Intent。
对于默认的standard方式,将会生成新的实例来处理每一个新的Intent。每个实例处理一个新的Intent。
对singleTop模式,如果一个已经存在的实例在目标task的栈顶,那么就重用这个实例来处理这个新的Intent,如果这个实例存在但是不在栈顶,那就不重用他,而是重新创建一个实例来处理这个新的Intent并且将这个实例压入栈。
例如现在有一个task堆栈ABCD,A是root Activity,D是栈顶Activity,现在有一个启动D的Intent来了,如果D是默认的standard方法,那么就会创建一个新的实例来处理这个Intent,所以这个堆栈就变为ABCDD,然而如果D是singleTop方式,这个已经存在的栈顶的D就会来处理这个Intent,所以堆栈还是ABCD。
如果另外一种情况,到来的Intent是给B的,不管B是standard还是singleTop(因为现在B不在栈顶),都会创建一个新的实例,所以堆栈变为ABCDB。
如上所述,一个"singleTask"或"singleInstance"模式的activity只会有一个实例,这样它们的实例就会处理所有的新intent。一个"singleInstance" activity总是在栈里的最上面(因为它是task里的唯一的activity), 这样它总是可以处理一个intent。而一个"singleTask" activity在栈里可以有或没有其他activity在它上面。如果有的话,它就不能对新到的intent进行处理,intent将被丢弃。(即使intent被丢弃,它的到来将使task来到前台,并维持在那里。)
当一个已有的Activity被请求去处理一个新的Intent时,Intent对象会通过onNewIntent()的调用传递给这个活动。(传递进来的原始的Intent对象可以通过调用getIntent()获取)。
注意,当创建一个新的Activity的实例来处理一个新收到的Intent时,用户可以按BACK键回到上一个状态(上一个Activity)。但是使用一个已有的Activity实例操作新收到的Intent时,用户不能通过按下BACK键回到这个实例在接受到新Intent之前的状态。
呵呵,不好意思,扯得有点多了,我们继续看我们的程序。
在这里,如果是对一个Activity实现时可以这样实现,如果有多个Activity,我们就需要在每个Activity里重写onKeyDown事件并捕捉用户是否按下HOME键。
为了实现方便,我们可以使用一个Service专门用于监听程序是否进入后台或前台工作,如果程序进入后台运行就显示Notification,这样不管程序中有多少个Activity就可以很方便的实现程序前后如切换。
为此,我在程序中新添加了一个AppStatusService 类,目的是监听程序是否在前后台运行,如果在后台运行则显示信息提示。代码如下:
import java.util.List;
import com.test.background.MainActivity;
import com.test.background.NotificationExtend;
import com.test.background.R;
import com.test.util.AppManager;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.IBinder;
import android.util.Log;
/**
* 监听程序是否在前后台运行Service
* @Description: 监听程序是否在前后台运行Service
* @FileName: AppStatusService.java
* @Package com.test.service
* @Author Hanyonglu
* @Date 2012-4-13 下午04:13:47
* @Version V1.0
*/
public class AppStatusService extends Service{
private static final String TAG = "AppStatusService";
private ActivityManager activityManager;
private String packageName;
private boolean isStop = false;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
packageName = this.getPackageName();
System.out.println("启动服务");
new Thread() {
public void run() {
try {
while (!isStop) {
Thread.sleep(1000);
if (isAppOnForeground()) {
Log.v(TAG, "前台运行");
} else {
Log.v(TAG, "后台运行");
showNotification();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
/**
* 程序是否在前台运行
* @return
*/
public boolean isAppOnForeground() {
// Returns a list of application processes that are running on the device
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) return false;
for (RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName)
&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("终止服务");
isStop = true;
}
// 显示Notification
public void showNotification() {
// 创建一个NotificationManager的引用
NotificationManager notificationManager = (
NotificationManager)getSystemService(
android.content.Context.NOTIFICATION_SERVICE);
// 定义Notification的各种属性
Notification notification = new Notification(
R.drawable.icon,"阅读器",
System.currentTimeMillis());
// 将此通知放到通知栏的"Ongoing"即"正在运行"组中
notification.flags |= Notification.FLAG_ONGOING_EVENT;
// 点击后自动清除Notification
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults = Notification.DEFAULT_LIGHTS;
notification.ledARGB = Color.BLUE;
notification.ledOnMS = 5000;
// 设置通知的事件消息
CharSequence contentTitle = "阅读器显示信息"; // 通知栏标题
CharSequence contentText = "推送信息显示,请查看……"; // 通知栏内容
Intent notificationIntent = new Intent(AppManager.context,AppManager.context.getClass());
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent contentIntent = PendingIntent.getActivity(
AppManager.context, 0, notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(
AppManager.context, contentTitle, contentText, contentIntent);
// 把Notification传递给NotificationManager
notificationManager.notify(0, notification);
}
}
在这里为了在信息提示栏里点击后能够返回到原来的Activity,需要在AppManager里记下我们当前的Activity。 完毕。^_^
最后,希望转载的朋友能够尊重作者的劳动成果,加上转载地址:http://www.cnblogs.com/hanyonglu/archive/2012/04/15/2450551.html 谢谢。
发表评论
-
SpringBoot Fat Jar解压运行
2018-06-28 21:40 2264SpringBoot已经成为当前最流行的微服务 ... -
一句话实现五星评分显示
2018-06-05 08:31 999Python: rate = 1 #rate 取值 ... -
来算google的可视化编程工具——Blockly,不仅仅是玩具
2017-10-16 21:34 33165Blockly - 来自Google的可 ... -
安卓动态分析工具 Inspeckage
2017-08-07 08:46 0工具介绍 一个基于Xposed 开发的应用动态分析工具 g ... -
Android逆向之旅---静态方式破解微信获取聊天记录和通讯录信息
2017-08-07 08:37 0一、猜想数据存放路径 微信现在是老少皆宜,大街小巷都在使用 ... -
破解微信数据库 并查询数据上传服务器
2017-08-07 08:29 0由于工作需求破解了微信的数据库 并获取想要的信息上传服 ... -
安卓黑科技之HOOK详解
2017-08-07 08:21 0本文带大家进入到安卓另一个世界 互联网攻防大战 Xpos ... -
安卓逆向之基于Xposed-ZjDroid脱壳
2017-08-07 08:18 0前言 之前介绍了普通常见的反编译模式 但对于使用了 360 ... -
十步以内完成精细web打印
2017-06-21 11:44 7391注意: 康虎云报表组 ... -
浏览器端精准打印或套打组件
2017-01-18 13:05 6706注意: 康虎云报表 ... -
让HTML5支持后置摄像头
2016-12-22 15:44 2217让HTML5支持后置摄像头: <!DOCTYPE h ... -
如何让三列div中间那个自适应宽度
2016-12-03 18:46 723效果如图: 直接上代码,具体看注释: < ... -
网站获取用户手机号码的方法、系统、客户端及服务器(坑爹的玩意儿)
2016-11-22 14:22 2291网站获取用户 ... -
疯狂软件对Oracle放弃Java EE的看法
2016-08-14 22:38 530来源:http://javaligang ... -
几个Java相关的思维导图
2016-03-17 13:07 962来源:http://blog.csdn.net/jackf ... -
jasperReport Applet 打印
2016-02-01 16:33 874Applet方式的原理是本地下载Applet以及Jas ... -
为Java说句公道话
2016-01-24 10:59 720为Java说句公道话 有些 ... -
快速提高Android开发效率的Web工具
2016-01-24 10:47 762快速提高Android开发效率的Web工具 在Goog ... -
Mybatis Generator配置详解(中文)_转
2015-12-17 16:44 925来自: http://www.jianshu.com/p/e ... -
一个提供大量数据模型的网站
2015-12-17 14:00 997网站地址是:http://www.databaseansw ...
相关推荐
在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识。 我们都知道,一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的,比如说,想要给用户展示一个地图的信息,...
在Android平台上,开发一款能够实现在后台运行以及熄屏状态下继续录像的应用是一项具有挑战性的任务。这个名为"Android后台背景录像、熄屏录像 .rar"的压缩包文件提供了相关的源码资源,帮助开发者理解并实现这样的...
"启动页白屏"、"如何判断应用前后台切换"、"透明状态栏"以及"动态切换桌面图标"是开发者经常会遇到的问题,下面将针对这些知识点进行详细讲解。 1. **启动页白屏** 启动页白屏通常是由于应用程序启动时加载资源或...
在Android操作系统中,程序的退出方式与iOS等其他系统有所不同,因为Android系统设计的理念是让应用程序在后台继续运行,以实现更好的多任务处理。然而,有些情况下用户或开发者可能希望实现一个明确的退出功能,...
本示例源程序提供了关于Android进度条对话框的实现,特别是如何根据操作阶段改变其显示形式。 首先,让我们了解Android中的两种主要进度条类型: 1. **水平进度条(Horizontal ProgressBar)**:它通常显示为一个...
这份“Android程序研发源码Android 图片浏览源码.rar”提供了一套用于实现Android平台上的图片浏览功能的源代码。下面,我们将深入探讨这个源码中涉及的关键知识点,以及如何利用这些知识点来开发一个高效的图片浏览...
在Android应用开发中,加载框(Loading Dialog)和对话框(Dialog)是常见的用户界面元素,用于提供一种反馈机制,告知用户程序正在进行后台处理或需要用户做出选择。本例着重探讨如何自定义加载框效果,特别是通过...
1. **加载动画**:在Android应用中,加载动画通常用于指示用户应用程序正在后台处理数据,防止用户在等待期间感到不耐烦。此Demo包含加载中状态的动画设计,可能包括旋转的菊花、逐行填充的进度条等形式,这些都是...
- **Service**:在后台执行长时间运行的操作,不会因为用户切换到其他应用程序而停止。 - **ContentProvider**:提供了一个统一的数据共享接口,使不同的应用程序能够访问同一数据源。 #### 四、Android用户界面...
2. **Activity**:作为用户界面的入口点,讲解Activity的生命周期及其在屏幕旋转、后台切换等场景下的处理方式。 3. **Intent**:Intent用于在组件间传递消息,实现不同Activity或Service之间的通信。 4. **布局...
为了解决这个问题,开发者通常会创建一个启动画面(Splash Screen),在主界面加载完成前显示,以提供一个平滑过渡的效果。 在"Android无闪烁启动画面程序源码"中,我们可以学习到以下关键知识点: 1. **启动画面...
本资料包“Android应用源码完全退出程序的方法.zip”聚焦于如何在Android应用程序中实现这一功能。以下是关于这一主题的详细知识讲解: 1. **Activity生命周期**: Android应用基于Activity堆栈进行管理,每个...
【Android新闻段子客户端】是一款基于Android 4.4及更高版本,并且使用JDK 1.8开发的移动应用程序。这款应用集成了多种功能,旨在为用户提供丰富的新闻资讯和娱乐内容,包括新闻模块、段子模块、趣图模块、首页跳转...
- **多任务处理**:Android系统通过后台处理支持多任务功能,用户可以轻松切换应用而不会丢失当前状态。 - **事件驱动的通知机制**:系统能够根据不同的事件触发相应的通知,如新消息到达、应用程序更新等。 - **...
实现一个数字或模拟时钟应用,展示如何使用Android提供的API来实现时间和日期显示功能。 - **4.15 动态输入日期与时间** 介绍如何实现日期和时间的选择功能,包括使用DatePicker和TimePicker组件。 - **4.16 猜猜...
- **Splash Screen(闪屏页)**:在应用程序真正启动前显示的一个临时页面,可以通过Java或Kotlin等编程语言实现。 - **主题加载**:根据应用主题动态生成启动画面,可以提供更好的用户体验。 - **使用第三方库**...
综上所述,Android设计规范旨在创造一个既统一又个性化的用户界面,通过优化硬件与软件的交互、精简屏幕上的操作、深化对用户心智模型的理解,以及运用直接操作和动画效果等原则,最终实现卓越的用户体验。...
**Activity透明**:可以通过设置`<activity>`标签中的`android:theme="@android:style/Theme.Translucent"`来实现Activity的透明效果。 **一次性关闭所有的Activity**:可以通过遍历ActivityManager中的所有...
#### 一、Android文件系统与应用程序架构 **1.1 Android文件系统** 在Android操作系统中,文件系统对于存储应用数据至关重要。Android提供了多种存储方案,包括内部存储、外部存储以及SQLite数据库等。 - **内部...