1 双进程伪守护的原理
开启2个服务分别在不同的进程里面,根据AIDL进行进程之间通信
本地服务跟远程服务互相绑定,当本地服务开启成功,开启远程服务,然后跟远程服务绑定。反之
当其中一个进程出现异常,另一个进程会马上把这个出现异常的进程重新启动。
2外部通知栏点击回到带数据的APP画面
参考地址http://write.blog.csdn.net/postedit
AIDL
package com.aidl;
interface ProecssXutils{
void getString();
}
Service
package service;
import com.aidl.ProecssXutils;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import broadcasereciver.Notification;
import class_.Constans;
public class LocalService extends Service {
private MyBilder mybilder;
@Override
public IBinder onBind(Intent intent) {
if (mybilder == null) {
mybilder = new MyBilder();
}
// TODO Auto-generated method stub
return mybilder;
}
class MyBilder extends ProecssXutils.Stub {
@Override
public void getString() throws RemoteException {
// TODO Auto-generated method stub
Log.i("远程服务绑定", "----------------");
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 服务启动成功
// TODO Auto-generated method stub
this.startService(new Intent(LocalService.this, RemoteService.class));// 当本地服务器启动成功,启动远程服务
this.bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);// 绑定远程服务
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);// 系统通知管理器
Intent inttt = new Intent(LocalService.this, Notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(LocalService.this, 0, inttt,
PendingIntent.FLAG_UPDATE_CURRENT);
// am.set(AlarmManager.ELAPSED_REALTIME,
// SystemClock.currentThreadTimeMillis(), pendingIntent);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.currentThreadTimeMillis(), 10 * 1000, pendingIntent);//设置轮询时间10秒一次
return START_STICKY;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// 连接成功
Toast.makeText(LocalService.this, "本地服务启动", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 连接异常
LocalService.this.startService(new Intent(LocalService.this, RemoteService.class));
LocalService.this.bindService(new Intent(LocalService.this, RemoteService.class), conn,
Context.BIND_IMPORTANT);
}
};
}
package service;
import com.aidl.ProecssXutils;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import broadcasereciver.Notification;
import service.LocalService.MyBilder;
public class RemoteService extends Service {
private MyBilder mybilder;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
class MyBilder extends ProecssXutils.Stub {
@Override
public void getString() throws RemoteException {
// TODO Auto-generated method stub
Log.i("远程服务绑定", "----------------");
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
this.startService(new Intent(RemoteService.this, LocalService.class));
this.bindService(new Intent(RemoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent inttt = new Intent(RemoteService.this, Notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(RemoteService.this, 0, inttt,
PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.currentThreadTimeMillis(), 10 * 1000, pendingIntent);//设置轮询时间10秒一次
return START_STICKY;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
if (mybilder == null) {
mybilder = new MyBilder();
}
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// 连接成功
Toast.makeText(RemoteService.this, "远程服务启动", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 连接异常
RemoteService.this.startService(new Intent(RemoteService.this, LocalService.class));
RemoteService.this.bindService(new Intent(RemoteService.this, LocalService.class), conn,
Context.BIND_IMPORTANT);
}
};
}
BroadcastReceiver
package broadcasereciver;
import android.R;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
public class Notification extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.i("Notification", "------------------");
Intent in = new Intent(context, ToNotification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);//当存在时,先把原来的取消,然后创建一个新的,在AlarmManager服务时,修改一个闹铃,用的比较笨的的方法,先取消,然后重新注册,其实加上这个参数就行了
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);//通知栏设置
builder.setContentTitle("服务开启").setContentText("text").setTicker("Ticker")
.setSmallIcon(R.drawable.alert_dark_frame).setContentIntent(pendingIntent).build();
//通过NotificationManager对象的notify方法来执行一行notification
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(2, builder.build());//执行通知栏
}
}
package broadcasereciver;
import activity.MainActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import class_.Constans;
import class_.SystemUtils;
public class ToNotification extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(SystemUtils.isAppAlive(context, "com.xcl.demo")){//判断进程是否存在
Intent ints= new Intent(context,MainActivity.class);
ints.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bun = new Bundle();
bun.putString("bundle", "进程存在");
ints.putExtra(Constans.FALG, bun);
context.startActivity(ints);
}else{
Intent intss = context.getPackageManager().getLaunchIntentForPackage("com.xcl.demo");//不存在重新启动APP
intss.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Bundle bun = new Bundle();
bun.putString("bundle", "进程不存在");
intss.putExtra(Constans.FALG, bun);
context.startActivity(intss);
}
}
}
Activity
package activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import class_.Constans;
import service.LocalService;
public class Login_ extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
final TextView tv = new TextView(this);
tv.setText("登陆界面");
setContentView(tv);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent it = new Intent(Login_.this,MainActivity.class);
if (getIntent().getBundleExtra(Constans.FALG) != null) {
tv.setText(getIntent().getBundleExtra(Constans.FALG).getString("bundle"));
it.putExtra(Constans.FALG, getIntent().getBundleExtra(Constans.FALG));
}
startActivity(it);
finish();
}
}, 3000);
}
}
package activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import class_.Constans;
import service.LocalService;
import service.RemoteService;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
TextView te = new TextView(this);
setContentView(te);
this.startService(new Intent(this,LocalService.class));//开启本地服务
this.startService(new Intent(this,RemoteService.class));//开启远程服务
if (getIntent().getBundleExtra(Constans.FALG) != null) {//当进程存在的时候 Bundler会存在值 参考ToNotification类
te.setText(getIntent().getBundleExtra(Constans.FALG).getString("bundle"));
} else {
te.setText("空值");//进程不存在 重启APP Bundler是NULL
}
}
}
工具类
package class_;
public class Constans {
public static final String FALG="bundle";//全局变量
}
package class_;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.util.List;
/**
* Created by liangzili on 15/8/3.
*/
public class SystemUtils {
/**
* 判断应用是否已经启动
* @param context 一个context
* @param packageName 要判断应用的包名
* @return boolean
*/
public static boolean isAppAlive(Context context, String packageName){
ActivityManager activityManager =
(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> processInfos
= activityManager.getRunningAppProcesses();
for(int i = 0; i < processInfos.size(); i++){
if(processInfos.get(i).processName.equals(packageName)){
Log.i("NotificationLaunch",
String.format("the %s is running, isAppAlive return true", packageName));
return true;
}
}
Log.i("NotificationLaunch",
String.format("the %s is not running, isAppAlive return false", packageName));
return false;
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xcl.demo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name="activity.Login_" >
<intent-filter>
<action android:name="android.intent.action.MAIN" >
</action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="activity.MainActivity"></activity>
<service
android:name="service.LocalService"
android:process=":remote" >
</service>
<service
android:name="service.RemoteService"
android:process=":push" >
</service>
<receiver
android:name="broadcasereciver.Notification"
android:process=":push" >
</receiver>
<receiver
android:name="broadcasereciver.ToNotification"
android:process=":push" >
</receiver>
</application>
</manifest>