没事走两步-应用代码

DaemonConfigurations.java

package com.marswin89.marsdaemon;
 
import android.content.Context;
 
/**
  * the configurations of Daemon SDK, contains two process configuration.
  * @author Mars
  *
  */
public class DaemonConfigurations {
     
     public final DaemonConfiguration    PERSISTENT_CONFIG;
     public final DaemonConfiguration    DAEMON_ASSISTANT_CONFIG;
     public final DaemonListener     LISTENER;
     
     public DaemonConfigurations(DaemonConfiguration persistentConfig, DaemonConfiguration daemonAssistantConfig){
         this .PERSISTENT_CONFIG = persistentConfig;
         this .DAEMON_ASSISTANT_CONFIG = daemonAssistantConfig;
         this .LISTENER = null ;
     }
     
     public DaemonConfigurations(DaemonConfiguration persistentConfig, DaemonConfiguration daemonAssistantConfig, DaemonListener listener){
         this .PERSISTENT_CONFIG = persistentConfig;
         this .DAEMON_ASSISTANT_CONFIG = daemonAssistantConfig;
         this .LISTENER = listener;
     }
     
     
     
     /**
      * the configuration of a daemon process, contains process name, service name and receiver name if Android 6.0
      * @author guoyang
      *
      */
     public static class DaemonConfiguration{
         
         public final String PROCESS_NAME;
         public final String SERVICE_NAME;
         public final String RECEIVER_NAME;
         
         public DaemonConfiguration(String processName, String serviceName, String receiverName){
             this .PROCESS_NAME = processName;
             this .SERVICE_NAME = serviceName;
             this .RECEIVER_NAME = receiverName;
         }
     }
     
     /**
      * listener of daemon for external
      *
      * @author Mars
      *
      */
     public interface DaemonListener {
         void onPersistentStart(Context context);
         void onDaemonAssistantStart(Context context);
         void onWatchDaemonDaed();
     }

}



DaemonClient.java


package com.marswin89.marsdaemon;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
 
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
 
/**
  *
  * @author Mars
  *
  */
public class DaemonClient implements IDaemonClient{
     private DaemonConfigurations mConfigurations;
     public DaemonClient(DaemonConfigurations configurations) {
         this .mConfigurations = configurations;
     }
     @Override
     public void onAttachBaseContext(Context base) {
         initDaemon(base);
     }
     
     
     private final String DAEMON_PERMITTING_SP_FILENAME  = "d_permit" ;
     private final String DAEMON_PERMITTING_SP_KEY       = "permitted" ;
     
     
     private BufferedReader mBufferedReader; //release later to save time
     
     
     /**
      * do some thing about daemon
      * @param base
      */
     private void initDaemon(Context base) {
         if (!isDaemonPermitting(base) || mConfigurations == null ){
             return ;
         }
         String processName = getProcessName();
         String packageName = base.getPackageName();
         
         if (processName.startsWith(mConfigurations.PERSISTENT_CONFIG.PROCESS_NAME)){
             IDaemonStrategy.Fetcher.fetchStrategy().onPersistentCreate(base, mConfigurations);
         } else if (processName.startsWith(mConfigurations.DAEMON_ASSISTANT_CONFIG.PROCESS_NAME)){
             IDaemonStrategy.Fetcher.fetchStrategy().onDaemonAssistantCreate(base, mConfigurations);
         } else if (processName.startsWith(packageName)){
             IDaemonStrategy.Fetcher.fetchStrategy().onInitialization(base);
         }
         
         releaseIO();
     }
     
     
     /* spend too much time !! 60+ms
     private String getProcessName(){
         ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
         int pid = android.os.Process.myPid();
         List infos = am.getRunningAppProcesses();
         for (int i = 0; i < infos.size(); i++) {
             RunningAppProcessInfo info = infos.get(i);
             if(pid == info.pid){
                 return info.processName;
             }
         }
         return null;
     }
     */
     
     private String getProcessName() {
         try {
             File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
             mBufferedReader = new BufferedReader(new FileReader(file));
             return mBufferedReader.readLine();
         } catch (Exception e) {
             e.printStackTrace();
             return null;
         }
     }
     
     /**
      * release reader IO
      */
     private void releaseIO(){
         if (mBufferedReader != null ){
             try {
                 mBufferedReader.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
             mBufferedReader = null ;
         }
     }
     
     private boolean isDaemonPermitting(Context context){
         SharedPreferences sp = context.getSharedPreferences(DAEMON_PERMITTING_SP_FILENAME, Context.MODE_PRIVATE);
         return sp.getBoolean(DAEMON_PERMITTING_SP_KEY, true );
     }
     
     protected boolean setDaemonPermiiting(Context context, boolean isPermitting) {
         SharedPreferences sp = context.getSharedPreferences(DAEMON_PERMITTING_SP_FILENAME, Context.MODE_PRIVATE);
         Editor editor = sp.edit();
         editor.putBoolean(DAEMON_PERMITTING_SP_KEY, isPermitting);
         return editor.commit();
     }
 
}


IDaemonStrategy.java

package com.marswin89.marsdaemon;
 
import com.marswin89.marsdaemon.strategy.DaemonStrategy21;
import com.marswin89.marsdaemon.strategy.DaemonStrategy22;
import com.marswin89.marsdaemon.strategy.DaemonStrategy23;
import com.marswin89.marsdaemon.strategy.DaemonStrategyUnder21;
import com.marswin89.marsdaemon.strategy.DaemonStrategyXiaomi;
 
import android.content.Context;
import android.os.Build;
 
/**
  * define strategy method
  *
  * @author Mars
  *
  */
public interface IDaemonStrategy {
     /**
      * Initialization some files or other when 1st time
      *
      * @param context
      * @return
      */
     boolean onInitialization(Context context);
 
     /**
      * when Persistent process create
      *
      * @param context
      * @param configs
      */
     void onPersistentCreate(Context context, DaemonConfigurations configs);
 
     /**
      * when DaemonAssistant process create
      * @param context
      * @param configs
      */
     void onDaemonAssistantCreate(Context context, DaemonConfigurations configs);
 
     /**
      * when watches the process dead which it watched
      */
     void onDaemonDead();
 
     
     
     /**
      * all about strategy on different device here
      *
      * @author Mars
      *
      */
     public static class Fetcher {
 
         private static IDaemonStrategy mDaemonStrategy;
 
         /**
          * fetch the strategy for this device
          *
          * @return the daemon strategy for this device
          */
         static IDaemonStrategy fetchStrategy() {
             if (mDaemonStrategy != null ) {
                 return mDaemonStrategy;
             }
             int sdk = Build.VERSION.SDK_INT;
             switch (sdk) {
                 case 23 :
                     mDaemonStrategy = new DaemonStrategy23();
                     break ;
                     
                 case 22 :
                     mDaemonStrategy = new DaemonStrategy22();
                     break ;
                 
                 case 21 :
                     if ( "MX4 Pro" .equalsIgnoreCase(Build.MODEL)){
                         mDaemonStrategy = new DaemonStrategyUnder21();
                     } else {
                         mDaemonStrategy = new DaemonStrategy21();
                     }
                     break ;
                 
                 default :
                     if (Build.MODEL != null && Build.MODEL.toLowerCase().startsWith( "mi" )){
                         mDaemonStrategy = new DaemonStrategyXiaomi();
                     } else if (Build.MODEL != null && Build.MODEL.toLowerCase().startsWith( "a31" )){
                         mDaemonStrategy = new DaemonStrategy21();
                     } else {
                         mDaemonStrategy = new DaemonStrategyUnder21();
                     }
                     break ;
             }
             return mDaemonStrategy;
         }
     }
}


PackageUtils.java 

package com.marswin89.marsdaemon;
 
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
 
/**
  * Utils to prevent component from third-party app forbidding
  *
  * @author Mars
  *
  */
public class PackageUtils {
     /**
      * set the component in our package default
      * @param context
      * @param componentClassName
      */
     public static void setComponentDefault(Context context, String componentClassName){
         PackageManager pm = context.getPackageManager();
         ComponentName componentName = new ComponentName(context.getPackageName(), componentClassName);
         pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
     }
     
     /**
      * get the component in our package default
      * @param context
      * @param componentClassName
      */
     public static boolean isComponentDefault(Context context, String componentClassName){
         PackageManager pm = context.getPackageManager();
         ComponentName componentName = new ComponentName(context.getPackageName(), componentClassName);
         return pm.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
}


IDaemonClient.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.marswin89.marsdaemon;
 
import android.content.Context;
 
/**
  *
  * @author Mars
  *
  */
public interface IDaemonClient {
     /**
      * override this method by {@link android.app.Application}

      * ****************************************************************
      * DO super.attchBaseContext() first !
      * ****************************************************************
      *
      * @param base
      */
     void onAttachBaseContext(Context base);
}

NativeDaemonBase.java 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.marswin89.marsdaemon;
 
import android.content.Context;
 
/**
  * native base class
  *
  * @author Mars
  *
  */
public class NativeDaemonBase {
     /**
      * used for native
      */
     protected   Context         mContext;
     
     public NativeDaemonBase(Context context){
         this .mContext = context;
     }
 
     /**
      * native call back
      */
     protected void onDaemonDead(){
         IDaemonStrategy.Fetcher.fetchStrategy().onDaemonDead();
     }
     
}

DaemonStrategy23.java

package com.marswin89.marsdaemon.strategy;
 
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
 
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
 
import com.marswin89.marsdaemon.DaemonConfigurations;
import com.marswin89.marsdaemon.IDaemonStrategy;
import com.marswin89.marsdaemon.nativ.NativeDaemonAPI21;
/**
  * the strategy in android API 23.
  *
  * @author Mars
  *
  */
public class DaemonStrategy23 implements IDaemonStrategy{
     private final static String INDICATOR_DIR_NAME                  = "indicators" ;
     private final static String INDICATOR_PERSISTENT_FILENAME       = "indicator_p" ;
     private final static String INDICATOR_DAEMON_ASSISTANT_FILENAME = "indicator_d" ;
     private final static String OBSERVER_PERSISTENT_FILENAME        = "observer_p" ;
     private final static String OBSERVER_DAEMON_ASSISTANT_FILENAME  = "observer_d" ;
     
     private IBinder                 mRemote;
     private Parcel                  mBroadcastData;
     private DaemonConfigurations    mConfigs;
 
     @Override
     public boolean onInitialization(Context context) {
         return initIndicatorFiles(context);
     }
 
     @Override
     public void onPersistentCreate( final Context context, DaemonConfigurations configs) {
         initAmsBinder();
         initBroadcastParcel(context, configs.DAEMON_ASSISTANT_CONFIG.RECEIVER_NAME);
         sendBroadcastByAmsBinder();
         
         Thread t = new Thread(){
             public void run() {
                 File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
                 new NativeDaemonAPI21(context).doDaemon(
                         new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath());
             };
         };
         t.start();
         
         ComponentName componentName = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
         Intent intent = new Intent();
         intent.setComponent(componentName);
         context.startService(intent);
         
         if (configs != null && configs.LISTENER != null ){
             this .mConfigs = configs;
             configs.LISTENER.onPersistentStart(context);
         }
     }
 
     @Override
     public void onDaemonAssistantCreate( final Context context, DaemonConfigurations configs) {
         initAmsBinder();
         initBroadcastParcel(context, configs.PERSISTENT_CONFIG.RECEIVER_NAME);
         sendBroadcastByAmsBinder();
         
         Thread t = new Thread(){
             public void run() {
                 File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
                 new NativeDaemonAPI21(context).doDaemon(
                         new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
                         new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath());
             };
         };
         t.start();
         
         ComponentName componentName = new ComponentName(context.getPackageName(), configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
         Intent intent = new Intent();
         intent.setComponent(componentName);
         context.startService(intent);
         
         if (configs != null && configs.LISTENER != null ){
             this .mConfigs = configs;
             configs.LISTENER.onDaemonAssistantStart(context);
         }
     }
     
     
     @Override
     public void onDaemonDead() {
         if (sendBroadcastByAmsBinder()){
             
             if (mConfigs != null && mConfigs.LISTENER != null ){
                 mConfigs.LISTENER.onWatchDaemonDaed();
             }
             
             android.os.Process.killProcess(android.os.Process.myPid());
         }
     }
     
     
     private void initAmsBinder(){
         Class activityManagerNative;
         try {
             activityManagerNative = Class.forName( "android.app.ActivityManagerNative" );
             Object amn = activityManagerNative.getMethod( "getDefault" ).invoke(activityManagerNative); 
             Field mRemoteField = amn.getClass().getDeclaredField( "mRemote" );
             mRemoteField.setAccessible( true );
             mRemote = (IBinder) mRemoteField.get(amn);
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (IllegalArgumentException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (NoSuchMethodException e) {
             e.printStackTrace();
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
        
     }
     
     
     @SuppressLint ( "Recycle" ) // when process dead, we should save time to restart and kill self, don`t take a waste of time to recycle
     private void initBroadcastParcel(Context context, String broadcastName){
         Intent intent = new Intent();
         ComponentName componentName = new ComponentName(context.getPackageName(), broadcastName);
         intent.setComponent(componentName);
         intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
         
         /*  
//      Object contextImpl = ((Application)context.getApplicationContext()).getBaseContext();
         //this context is ContextImpl, get MainThread instance immediately
         Field mainThreadField = context.getClass().getDeclaredField("mMainThread");
         mainThreadField.setAccessible(true);
         Object mainThread = mainThreadField.get(context);
         //get ApplicationThread instance
         Object applicationThread = mainThread.getClass().getMethod("getApplicationThread").invoke(mainThread); 
         //get Binder
         Binder callerBinder = (Binder) (applicationThread.getClass().getMethod("asBinder").invoke(applicationThread));
          */
       
//          UserHandle userHandle = android.os.Process.myUserHandle();
//          int handle = (Integer) userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
         
         mBroadcastData = Parcel.obtain();
         mBroadcastData.writeInterfaceToken( "android.app.IActivityManager" );
//          mBroadcastData.writeStrongBinder(callerBinder);
         mBroadcastData.writeStrongBinder( null );
         intent.writeToParcel(mBroadcastData, 0 );
         mBroadcastData.writeString(intent.resolveTypeIfNeeded(context.getContentResolver()));
         mBroadcastData.writeStrongBinder( null );
         mBroadcastData.writeInt(Activity.RESULT_OK);
         mBroadcastData.writeString( null );
         mBroadcastData.writeBundle( null );
         mBroadcastData.writeString( null );
         mBroadcastData.writeInt(- 1 );
         mBroadcastData.writeInt( 0 );
         mBroadcastData.writeInt( 0 );
//          mBroadcastData.writeInt(handle);
         mBroadcastData.writeInt( 0 );
     }
     
     
     private boolean sendBroadcastByAmsBinder(){
         
         try {
             if (mRemote == null || mBroadcastData == null ){
                 Log.e( "Daemon" , "REMOTE IS NULL or PARCEL IS NULL !!!" );
                 return false ;
             }
             mRemote.transact( 14 , mBroadcastData, null , 0 ); //BROADCAST_INTENT_TRANSACTION = 0x00000001 + 13
             return true ;
         } catch (RemoteException e) {
             e.printStackTrace();
             return false ;
         }
     }
     
     
     
     private boolean initIndicatorFiles(Context context){
         File dirFile = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
         if (!dirFile.exists()){
             dirFile.mkdirs();
         }
         try {
             createNewFile(dirFile, INDICATOR_PERSISTENT_FILENAME);
             createNewFile(dirFile, INDICATOR_DAEMON_ASSISTANT_FILENAME);
             return true ;
         } catch (IOException e) {
             e.printStackTrace();
             return false ;
         }
     }
     
     private void createNewFile(File dirFile, String fileName) throws IOException{
         File file = new File(dirFile, fileName);
         if (!file.exists()){
             file.createNewFile();
         }
     }
}

DaemonStrategyXiaomi.java

package com.marswin89.marsdaemon.strategy;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
 
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
 
import com.marswin89.marsdaemon.DaemonConfigurations;
import com.marswin89.marsdaemon.IDaemonStrategy;
import com.marswin89.marsdaemon.nativ.NativeDaemonAPI20;
 
/**
  * the strategy in Mi.
  *
  * @author Mars
  *
  */
public class DaemonStrategyXiaomi implements IDaemonStrategy{
     private final String BINARY_DEST_DIR_NAME   = "bin" ;
     private final String BINARY_FILE_NAME       = "daemon" ;
     
     private IBinder                 mRemote;
     private Parcel                  mServiceData;
     private DaemonConfigurations    mConfigs;
     
     @Override
     public boolean onInitialization(Context context) {
         return installBinary(context);
     }
 
     @Override
     public void onPersistentCreate( final Context context, final DaemonConfigurations configs) {
         initAmsBinder();
         initServiceParcel(context, configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
         Thread t = new Thread(){
             public void run() {
                 File binaryFile = new File(context.getDir(BINARY_DEST_DIR_NAME, Context.MODE_PRIVATE), BINARY_FILE_NAME);
                 new NativeDaemonAPI20(context).doDaemon(
                         context.getPackageName(),
                         configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME,
                         binaryFile.getAbsolutePath());
             };
         };
         t.setPriority(Thread.MAX_PRIORITY);
         t.start();
         
         if (configs != null && configs.LISTENER != null ){
             this .mConfigs = configs;
             configs.LISTENER.onPersistentStart(context);
         }
         
     }
     
     
     @Override
     public void onDaemonAssistantCreate(Context context, DaemonConfigurations configs) {
         Intent intent = new Intent();
         ComponentName component = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
         intent.setComponent(component);
         context.startService(intent);
         if (configs != null && configs.LISTENER != null ){
             configs.LISTENER.onWatchDaemonDaed();
         }
         android.os.Process.killProcess(android.os.Process.myPid());
     }
 
     @Override
     public void onDaemonDead() {
         if (startServiceByAmsBinder()){
             
             if (mConfigs != null && mConfigs.LISTENER != null ){
                 mConfigs.LISTENER.onWatchDaemonDaed();
             }
             
             android.os.Process.killProcess(android.os.Process.myPid());
         }
     }
     
     private void initAmsBinder(){
         Class activityManagerNative;
         try {
             activityManagerNative = Class.forName( "android.app.ActivityManagerNative" );
             Object amn = activityManagerNative.getMethod( "getDefault" ).invoke(activityManagerNative); 
             Field mRemoteField = amn.getClass().getDeclaredField( "mRemote" );
             mRemoteField.setAccessible( true );
             mRemote = (IBinder) mRemoteField.get(amn);
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (IllegalArgumentException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (NoSuchMethodException e) {
             e.printStackTrace();
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
        
     }
     
     
     @SuppressLint ( "Recycle" ) // when process dead, we should save time to restart and kill self, don`t take a waste of time to recycle
     private void initServiceParcel(Context context, String serviceName){
         Intent intent = new Intent();
         ComponentName component = new ComponentName(context.getPackageName(), serviceName);
         intent.setComponent(component);
         
         /* 
         //get ContextImpl instance
//          Object contextImpl = ((Application)context.getApplicationContext()).getBaseContext();
           //this context is ContextImpl, get MainThread instance immediately
           Field mainThreadField = context.getClass().getDeclaredField("mMainThread");
           mainThreadField.setAccessible(true);
           Object mainThread = mainThreadField.get(context);
           //get ApplicationThread instance
           Object applicationThread = mainThread.getClass().getMethod("getApplicationThread").invoke(mainThread); 
           //get Binder
           Binder callerBinder = (Binder) (applicationThread.getClass().getMethod("asBinder").invoke(applicationThread)); 
           */
           
           //get handle
//          UserHandle userHandle = android.os.Process.myUserHandle();
//          int handle = (Integer) userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
           
           //write pacel
           mServiceData = Parcel.obtain();
           mServiceData.writeInterfaceToken( "android.app.IActivityManager" );
           mServiceData.writeStrongBinder( null );
//          mServiceData.writeStrongBinder(callerBinder);
           intent.writeToParcel(mServiceData, 0 );
           mServiceData.writeString( null );
//          mServiceData.writeString(intent.resolveTypeIfNeeded(context.getContentResolver()));
           mServiceData.writeInt( 0 );
//          mServiceData.writeInt(handle);
         
     }
     
     private boolean startServiceByAmsBinder(){
         try {
             if (mRemote == null || mServiceData == null ){
                 Log.e( "Daemon" , "REMOTE IS NULL or PARCEL IS NULL !!!" );
                 return false ;
             }
             mRemote.transact( 34 , mServiceData, null , 0 ); //START_SERVICE_TRANSACTION = 34
             return true ;
         } catch (RemoteException e) {
             e.printStackTrace();
             return false ;
         }
     }
     
     private boolean installBinary(Context context){
         String binaryDirName = null ;
//      String abi = Build.CPU_ABI;
//      if (abi.startsWith("armeabi-v7a")) {
//          binaryDirName = "armeabi-v7a";
//      }else if(abi.startsWith("x86")) {
//          binaryDirName = "x86";
//      }else{
//          binaryDirName = "armeabi";
//      }
         return install(context, BINARY_DEST_DIR_NAME, binaryDirName, BINARY_FILE_NAME);
     }
     
     
     private boolean install(Context context, String destDirName, String assetsDirName, String filename) {
         File file = new File(context.getDir(destDirName, Context.MODE_PRIVATE), filename);
         if (file.exists()) {
             return true ;
         }
         try {
             copyAssets(context, (TextUtils.isEmpty(assetsDirName) ? "" : (assetsDirName + File.separator)) + filename, file, "700" );
             return true ;
         } catch (Exception e) {
             return false ;
         }
     }
     
     private void copyAssets(Context context, String assetsFilename, File file, String mode) throws IOException, InterruptedException {
         AssetManager manager = context.getAssets();
         final InputStream is = manager.open(assetsFilename);
         copyFile(file, is, mode);
     }
     
     private void copyFile(File file, InputStream is, String mode) throws IOException, InterruptedException {
         if (!file.getParentFile().exists()){
             file.getParentFile().mkdirs();
         }
         final String abspath = file.getAbsolutePath();
         final FileOutputStream out = new FileOutputStream(file);
         byte buf[] = new byte [ 1024 ];
         int len;
         while ((len = is.read(buf)) > 0 ) {
             out.write(buf, 0 , len);
         }
         out.close();
         is.close();
         Runtime.getRuntime().exec( "chmod " + mode + " " + abspath).waitFor();
     }
 
}


DaemonStrategy21.java

package com.marswin89.marsdaemon.strategy;
 
import java.io.File;
import java.io.IOException;
 
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
 
import com.marswin89.marsdaemon.DaemonConfigurations;
import com.marswin89.marsdaemon.IDaemonStrategy;
import com.marswin89.marsdaemon.nativ.NativeDaemonAPI21;
/**
  * the strategy in android API 21.
  *
  * @author Mars
  *
  */
public class DaemonStrategy21 implements IDaemonStrategy{
     private final static String INDICATOR_DIR_NAME                  = "indicators" ;
     private final static String INDICATOR_PERSISTENT_FILENAME       = "indicator_p" ;
     private final static String INDICATOR_DAEMON_ASSISTANT_FILENAME = "indicator_d" ;
     private final static String OBSERVER_PERSISTENT_FILENAME        = "observer_p" ;
     private final static String OBSERVER_DAEMON_ASSISTANT_FILENAME  = "observer_d" ;
     
     private AlarmManager            mAlarmManager;
     private PendingIntent           mPendingIntent;
     private DaemonConfigurations    mConfigs;
 
     @Override
     public boolean onInitialization(Context context) {
         return initIndicators(context);
     }
 
     @Override
     public void onPersistentCreate( final Context context, DaemonConfigurations configs) {
         Intent intent = new Intent();
         ComponentName componentName = new ComponentName(context.getPackageName(), configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
         intent.setComponent(componentName);
         context.startService(intent);
         
         initAlarm(context, configs.PERSISTENT_CONFIG.SERVICE_NAME);
         
         Thread t = new Thread(){

你可能感兴趣的:(没事走两步-应用代码)