天天看點

安卓雙程序保活的代碼

首先要聲明,雙程序保活,不是為了解決被殺之後複活的問題。因為在新版本的安卓上,這個辦法已經不靈了(也許有人有更好的辦法?)。這裡介紹這個雙程序保活,是為在電視盒子上的應用。如果程序死了,有的系統會自動啟動,有的就不會。而有的應用在電視盒子上必須常線上。

 本文實作方法,與其他介紹的原理一樣,代碼更加精練。為什麼呢?因為使用了繼承。

 首先寫一個AIDL:

package com.csdn;
 
interface IKeepAliveServiceConnection
{
    String getProcessName();
}      

然後寫一個父類:

package com.keepalive;
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.util.Log;
 
import com.newayte.nvideo.IKeepAliveServiceConnection;
 
 
public abstract class KeepAliveService extends Service
{
    private static final String TAG = KeepAliveService.class.getCanonicalName();
 
    private static final String KEEP_ALIVE = "keep-alive";
 
 
    private KeepAliveBinder mKeepAliveBinder;
    private KeepAliveServiceConnection mKeepAliveConnection;
 
    @Override
    public void onCreate()
    {
        super.onCreate();
 
        if (mKeepAliveBinder == null)
        {
            mKeepAliveBinder = new KeepAliveBinder();
            mKeepAliveConnection = new KeepAliveServiceConnection();
        }
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        bindService(getConnectionIntent(), mKeepAliveConnection, Context.BIND_IMPORTANT);
 
        Log.d(TAG, "onStartCommand()");
        /*PendingIntent contentIntent = PendingIntent.getService(this, 0, intent, 0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setTicker("CSDN")
                .setContentIntent(contentIntent)
                .setContentTitle("TITLE")
                .setAutoCancel(true)
                .setContentText("CONTENT")
                .setWhen( System.currentTimeMillis());
        //把service設定為前台運作
        startForeground(startId, builder.build());*/
 
        return START_STICKY;
    }
 
    @Override
    public IBinder onBind(Intent intent)
    {
        //子類如果跟其他程序綁定時,從父類得到的binder不為空,說明是從保活服務啟動的。
        Log.d(TAG, KEEP_ALIVE+"="+intent.getBooleanExtra(KEEP_ALIVE, false)+", "+intent);
        if (intent.getBooleanExtra(KEEP_ALIVE, false))
        {
            return mKeepAliveBinder;
        }
        return null;
    }
 
    private Intent getConnectionIntent()
    {
        Intent intent = new Intent(KeepAliveService.this, getPeerService());
        intent.putExtra(KEEP_ALIVE, true);
        return intent;
    }
 
    class KeepAliveBinder extends IKeepAliveServiceConnection.Stub
    {
        @Override
        public String getProcessName() throws RemoteException
        {
            return getServiceName();
        }
    }
 
    class KeepAliveServiceConnection implements ServiceConnection
    {
 
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            Log.d(TAG, getPeerService().getCanonicalName()+"建立連接配接成功!");
        }
 
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.d(TAG, getPeerService().getCanonicalName()+"服務程序已死。重新啟動并建立連結。");
            //啟動被幹掉的
            KeepAliveService.this.startService(getConnectionIntent());
            KeepAliveService.this.bindService(getConnectionIntent(), mKeepAliveConnection, Context.BIND_IMPORTANT);
        }
 
    }
 
    /**
     * 這兩個并不是必要的。
     * 考慮到子類,還是要有點代碼的。
     *
     * @return
     */
    protected abstract String   getServiceName();
 
    protected abstract Class<?> getPeerService();
 
}      

子類服務助手(怎麼樣?使用了繼承,極為簡單吧):

package com.keepalive;
 
public class AssistantServiceTv extends KeepAliveService
{
 
    @Override
    protected String   getServiceName()
    {
        return AssistantServiceTv.class.getCanonicalName();
    }
 
    @Override
    protected Class<?> getPeerService()
    {
        return NetworkServiceTv.class;
    }
 
}      

主服務(注意onBind()的代碼):

package com.keepalive;
 
public class NetworkServiceTv extends KeepAliveService
{
    @Override
    public IBinder onBind(Intent intent)
    {
        Log.d(TAG, "service onBind="+intent);
        IBinder binder = super.onBind(intent);
        if (null != binder)
        {
            return binder;
        }
        return mBinder;
    }
 
    @Override
    protected String   getServiceName()
    {
        return NetworkServiceTv.class.getCanonicalName();
    }
 
    @Override
    protected Class<?> getPeerService()
    {
        return AssistantServiceTv.class;
    }
 
}      

在NetworkServiceTv中負責聯網。這樣即使其中一個程序因錯誤崩潰,也可以被啟動再次聯網。

繼續閱讀