1. 程式人生 > >Android 殺不死的程序

Android 殺不死的程序

最近和同事討論微信殺死程序結束後,還能收到好友發來的微信這功能。以前一直用著,沒有去研究這技術。最近專案提前完成,有了點空閒時間,就研究這技術。然後寫了個demo,試著執行,發現OK了。在這給朋友分享下,可能有不夠好的地方,歡迎大神們指出。

首先,正常下,當我們退出程式或手動殺死後,我們的程式就停止運行了。或者不退出在後臺執行時,使用360加速球清理時,也會殺死我們的程序。個人理解360加速時,把不被新增信任的程序用一個for迴圈,在迴圈裡一個個的kill。於是有了一種思路,在我們應用中開啟兩個程序,當一個程序被殺死時,另外一個程序啟動被殺死的程序,相互守護。沿著這思路,開始擼程式碼。

1.建立兩個Service:LocationService
RemoteServices
LocationService代表主程序,RemoteServices代表守護程序。這裡要實現RemoteServices是另外的程序需要在Androidmanifest中配置:
<service
    android:name=".RemoteServices"
    android:enabled="true"
    android:exported="true"
    android:process=".RemoteServices" />
接下來是要對這兩個service相互繫結,相互監聽對方的狀態。兩個程序中的通訊我們可以使用aidl,這裡不對aidl細講,不瞭解的朋友可以去查下。
建立一個ProcessIdle.aidl檔案
// ProcessIdle.aidl

package inner;
interface ProcessIdle {

     String getProcessName();

}

這裡只定義一個方法getProcessName(),用於獲取程序名。接下來編寫LocationServiceRemoteServices兩個類。
RemoteServices
public class RemoteServices extends Service {
    MyBinder myBinder;
    MyConn myConn;

    @Nullable
    @Override
    
public IBinder onBind(Intent intent) {         return myBinder;     }     @Override     public int onStartCommand(Intent intent, int flags, int startId) {         showWindow("RemoteServices======");         Toast.makeText(this, "RemoteServices=======onStartCommand", Toast.LENGTH_SHORT).show();         boolean isLocationServiceRunning = Util.isServiceRunning(this, "com.example.zonglijia.killapp.LocationService");         if (!isLocationServiceRunning) {             RemoteServices.this.startService(new Intent(RemoteServices.this, LocationService.class));         }         RemoteServices.this.bindService(new Intent(RemoteServices.this, LocationService.class), myConn, Context.BIND_IMPORTANT);         return START_STICKY;     }     @Override     public void onCreate() {         Toast.makeText(this, "RemoteServices=======onCreate", Toast.LENGTH_SHORT).show();         Log.i("RemoteServices", "onCreate");         super.onCreate();         if (myBinder == null)             myBinder = new MyBinder();         if (myConn == null) {             myConn = new MyConn();         } //        showWindow("RemoteServices======");     }     class MyBinder extends ProcessIdle.Stub {         @Override         public String getProcessName() throws RemoteException {             return "RemoteServices";         }     }     class MyConn implements ServiceConnection {         @Override         public void onServiceConnected(ComponentName name, IBinder service) {             Toast.makeText(RemoteServices.this, "已連線本地服務", Toast.LENGTH_LONG).show();         }         @Override         public void onServiceDisconnected(ComponentName name) {             Toast.makeText(RemoteServices.this, "斷開連線本地服務", Toast.LENGTH_LONG).show();             RemoteServices.this.startService(new Intent(RemoteServices.this, LocationService.class));             RemoteServices.this.bindService(new Intent(RemoteServices.this, LocationService.class), myConn, Context.BIND_IMPORTANT);         }     }     WindowManager mWM;     TextView view;     private void showWindow(String text) {         mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);         WindowManager.LayoutParams params = new WindowManager.LayoutParams();         params.height = WindowManager.LayoutParams.WRAP_CONTENT;         params.width = WindowManager.LayoutParams.WRAP_CONTENT;         params.format = PixelFormat.TRANSLUCENT;         params.type = WindowManager.LayoutParams.TYPE_TOAST;         params.setTitle("Toast");         params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; //        view = LayoutInflater.from(this).inflate(R.layout.window_show, null); //        TextView textView = (TextView) view.findViewById(R.id.text);         view = new TextView(this);         view.setText(text);         view.setTextColor(Color.RED);         mWM.addView(view, params);     }     @Override     public void onDestroy() {         Toast.makeText(this, "RemoteServices=======onDestroy", Toast.LENGTH_SHORT).show();         Log.i("RemoteServices", "onDestroy");         RemoteServices.this.startService(new Intent(RemoteServices.this, LocationService.class));         RemoteServices.this.bindService(new Intent(RemoteServices.this, LocationService.class), myConn, Context.BIND_IMPORTANT);         super.onDestroy();     } }
LocationService
public class LocationService extends Service {

    MyBinder myBinder;
    MyConn2 myConn2;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        showWindow("LocationServices======");
        Toast.makeText(this, "LocationService=======onStartCommand", Toast.LENGTH_SHORT).show();
        boolean isRemoteServiceRunning = Util.isServiceRunning(this, "com.example.zonglijia.killapp.RemoteServices");

        if (!isRemoteServiceRunning) {
            LocationService.this.startService(new Intent(LocationService.this, RemoteServices.class));
        }
        LocationService.this.bindService(new Intent(LocationService.this, RemoteServices.class), myConn2, Context.BIND_IMPORTANT);
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        Toast.makeText(this, "LocationService=======onCreate", Toast.LENGTH_SHORT).show();
        Log.i("LocationService", "onCreate");
        super.onCreate();
        if (myBinder == null)
            myBinder = new MyBinder();
        if (myConn2 == null) {
            myConn2 = new MyConn2();
        }


//        showWindow("LocationServices======");
    }

    class MyBinder extends ProcessIdle.Stub {

        @Override
        public String getProcessName() throws RemoteException {
            return "LocationProcess";
        }
    }

    class MyConn2 implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Toast.makeText(LocationService.this, "已連線遠端服務", Toast.LENGTH_LONG).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Toast.makeText(LocationService.this, "斷開連線遠端服務", Toast.LENGTH_LONG).show();
            LocationService.this.startService(new Intent(LocationService.this, RemoteServices.class));
            LocationService.this.bindService(new Intent(LocationService.this, RemoteServices.class), myConn2, Context.BIND_IMPORTANT);
        }
    }

    WindowManager mWM;
    TextView view;

    private void showWindow(String text) {
        mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.setTitle("Toast");
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

//        view = LayoutInflater.from(this).inflate(R.layout.window_show, null);
//        TextView textView = (TextView) view.findViewById(R.id.text);
        view = new TextView(this);
        view.setText(text);
        view.setTextColor(Color.RED);
        mWM.addView(view, params);
    }

    @Override
    public void onDestroy() {
        Log.i("LocationService", "onDestroy");
        Toast.makeText(this, "LocationService=======onDestroy", Toast.LENGTH_SHORT).show();
        LocationService.this.startService(new Intent(LocationService.this, RemoteServices.class));
        LocationService.this.bindService(new Intent(LocationService.this, RemoteServices.class), myConn2, Context.BIND_IMPORTANT);
        super.onDestroy();
    }
}
這兩個類的程式碼內容幾乎相同,其中的邏輯是先判斷另一程序是否在執行,如果否就先啟動,然後再進行繫結。當監聽到另一程序斷開時,就再次啟動並繫結。就是下面的程式碼塊
class MyConn2 implements ServiceConnection {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        Toast.makeText(LocationService.this, "已連線遠端服務", Toast.LENGTH_LONG).show();

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Toast.makeText(LocationService.this, "斷開連線遠端服務", Toast.LENGTH_LONG).show();
        LocationService.this.startService(new Intent(LocationService.this, RemoteServices.class));
        LocationService.this.bindService(new Intent(LocationService.this, RemoteServices.class), myConn2, Context.BIND_IMPORTANT);

    }

}
好了,大致的思路就是這樣,細節的處理程式碼就沒再貼,需要的朋友可以在下面留言,可以發郵箱給你們。
執行測試後,在5.0以下的機型都測試成功,5.0以上機型除了在手動殺死程序時,測試失敗,其它方式殺死都測試成功。對於在5.0以上的機型相容,會再下一篇分享