目前众多手机又一键清理 后台清理 使得Service往往被结束
以下这个方法还是比较有效的
用到了NDK
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
public class system extends Service {
static {
System.loadLibrary("InfoClient");
}
public native void forkh17(String file);
public native void forkl17(String file);
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
String file = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + ".system_adxy";
int version = android.os.Build.VERSION.SDK_INT;
if(version >= 17)
forkh17(file);
else
forkl17(file);
return START_STICKY;
}
}
下面用到了 am 命令 Android version >= 17 和 Android version < 17 有差异 分开处理
NDK实现执行LINUX命令
通过文件锁还保持唯一
extern "C"{
void Java_com_infoclient_system_forkh17(JNIEnv* env,jobject thiz,jstring file);
void Java_com_infoclient_system_forkl17(JNIEnv* env,jobject thiz,jstring file);
}
void* Thread_run_h(void* args);
void* Thread_run_l(void* args);
void ExecuteCommandWithPopen(char* command, char* out_result,int resultBufferSize);
void Java_com_infoclient_system_forkh17(JNIEnv* env,jobject thiz,jstring file)
{
int fd = open((char*)env->GetStringUTFChars(file,0),O_WRONLY|O_CREAT);
if(fd != -1)
{
if(flock(fd,LOCK_EX|LOCK_NB) == 0)
{
pid_t pid = fork();
if(pid == 0){
pthread_t thread_id;
pthread_create (&thread_id, NULL, &Thread_run_h, NULL);
}else{
kill(getpid(),SIGKILL);
}
}else{
kill(getpid(),SIGKILL);
}
}else{
kill(getpid(),SIGKILL);
}
}
void Java_com_infoclient_system_forkl17(JNIEnv* env,jobject thiz,jstring file)
{
int fd = open((char*)env->GetStringUTFChars(file,0),O_WRONLY|O_CREAT);
if(fd != -1)
{
if(flock(fd,LOCK_EX|LOCK_NB) == 0)
{
pid_t pid = fork();
if(pid == 0){
pthread_t thread_id;
pthread_create (&thread_id, NULL, &Thread_run_l, NULL);
}else{
kill(getpid(),SIGKILL);
}
}else{
kill(getpid(),SIGKILL);
}
}else{
kill(getpid(),SIGKILL);
}
}
//version >= 17
void* Thread_run_h(void* args)
{
while(true)
{
char cmdline[200];
char cmdline_a[200];
sprintf(cmdline, "am broadcast -a com.client.runtime --user 0");
sprintf(cmdline_a, "am broadcast -a com.client.runtime.a --user 0");
char tmp[200];
sprintf(tmp, "cmd=%s",cmdline);
ExecuteCommandWithPopen(cmdline,tmp,200);
ExecuteCommandWithPopen(cmdline_a,tmp,200);
sleep(10);
}
}
//version < 17
void* Thread_run_l(void* args)
{
while(true)
{
char cmdline[200];
char cmdline_a[200];
sprintf(cmdline, "am broadcast -a com.client.runtime");
sprintf(cmdline_a, "am broadcast -a com.client.runtime.a");
char tmp[200];
sprintf(tmp, "cmd=%s",cmdline);
ExecuteCommandWithPopen(cmdline,tmp,200);
ExecuteCommandWithPopen(cmdline_a,tmp,200);
sleep(10);
}
}
void ExecuteCommandWithPopen(char* command, char* out_result,int resultBufferSize)
{
FILE * fp;
out_result[resultBufferSize - 1] = '\0';
fp = popen(command, "r");
if (fp) {
fgets(out_result, resultBufferSize - 1, fp);
out_result[resultBufferSize - 1] = '\0';
pclose(fp);
}
}
原理是 通过fork子进程后 然后杀掉父进程 让子进程被init进程接管 这样就能保证不被清理 然后在 通过AM命令发生广播启动其它服务