android APP后台服务可以长期与服务器进行长期的交互,保证数据的实时性,这个小项目主要实现的是在app退出之后依然可以运行服务。使用系统的Intent.ACTION_TIME_TICK进行实现,这个系统的广播每隔一分钟就进行广播一次,可以在程序中接收该广播消息,接收到之后检测app中的service服务是否在运行,如果在运行,则不处理,如果没有运行,则重新启动该service服务。
值得注意的是,虽然本示例可以实现后台运行服务的功能,但是当用户按home键进行清楚内存的时候依然可以把app清楚内存。app清楚内存之后,不再运行,当然也就不能实现什么功能(如接收消息推送),就是达不到像QQ、微信那样,清楚内存之后,QQ和微信依然在后台运行。
下面开始讲述本项目的实现过程。
我们知道,注册广播接收者有两种方式,一种是在配置文件中进行配置,另一种是在代码中进行注册。该广播需要在代码中进行注册。这里需要注意的是注册广播接收者可以在Activity中进行注册,但是如果在Activity中进行注册,必须在onDestory的时候进行注销广播接收者,如果不注销,会出现Error错误。有因为希望该广播接收者在app退出之后,依然能够接收到系统广播消息,所以此处注册系统的广播接受者应该在Application类中完成。
代码如下:
public class MyApplication extends Application {
private static MyApplication myApplication;
public MyApplication() {
}
public static MyApplication getInstance(){
if (myApplication == null) {
myApplication = new MyApplication();
}
return myApplication;
}
@Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_TIME_TICK);
MyReceiver myReceiver = new MyReceiver();
registerReceiver(myReceiver, intentFilter);
}
}
在接收到系统广播的消息之后,利用自定义的广播接受者MyReceiver进行处理,在onReceive方法中检测要启动的Service类是否已经在后台运行,如果在后台运行,则不处理,如果没有在后台运行,则启动该服务。代码如下:
public class MyReceiver extends BroadcastReceiver {
private final String TAG = MyReceiver.class.getSimpleName();
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Log.i(TAG, "监听到开机启动getAction");
}else if(intent.getAction().equals(Intent.ACTION_TIME_TICK)){
Log.i(TAG, "监听到TIME_TICK");
boolean isServiceRunning = false;
ActivityManager manager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service :manager.getRunningServices(Integer.MAX_VALUE)) {
if("com.yin.service.MyService".equals(service.service.getClassName()))
//Service的全类名
{
isServiceRunning = true;
Log.i(TAG, "已经启动");
}
}
if (!isServiceRunning) {
Intent i = new Intent(context, MyService.class);
context.startService(i);
Log.i(TAG, "没有启动,现在启动");
}
}else {
Log.i(TAG, "监听到其他");
}
}
}
下面给出MyService类的代码,该代码并不完成什么功能
public class MyService extends Service {
private final String TAG = MyService.class.getSimpleName();
public MyService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
//使用这样的标志因为该值会让系统在该service停止之后在进行启动,但是在清除内存之后是无效的
return super.onStartCommand(intent,flags,startId);
}
@Override
public void onCreate() {
super.onCreate();
Notification notification = new Notification();
startForeground(-1, notification);
Log.i(TAG, "Myservice类的oncreate方法");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Intent service = new Intent(this, MyService.class);
startService(service);//这里是一个取巧的方法,在该service销毁是在进行启动,但是清楚该app内存之后依然不能起作用
}
}
下面给出配置文件代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yin.servicetest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="20" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:persistent="true"
android:name="com.yin.application.MyApplication" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.yin.servicetest.MyReceiver">
</receiver>
<service android:name="com.yin.service.MyService">
</service>
</application>
</manifest>
结果:
值得注意的是,虽然那可以达到后台运行的目的,但是如果在用户清楚内存之后这样的方法就不起作用了。如果大家有谁知道QQ或者微信如何实现在清楚内存之后如何实现依然在后台运行进程和服务的,请不吝赐教!【握手】
源码下载