android 服务常驻

目前众多手机又一键清理 后台清理 使得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命令发生广播启动其它服务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值