专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
stormzhang  ·  最后一次通知 ·  昨天  
鸿洋  ·  简洁高效:类抖音视频列表设计思路 ·  2 天前  
stormzhang  ·  打工人何苦为难打工人 ·  3 天前  
鸿洋  ·  好用的HarmonyOS Next ... ·  4 天前  
51好读  ›  专栏  ›  安卓开发精选

Android 通过JNI实现守护进程(下)

安卓开发精选  · 公众号  · android  · 2016-10-25 11:38

正文

(点击上方公众号,可快速关注)


来源:LeBron_Six  

链接:blog.csdn.net/yyh352091626/article/details/50542554


接上文


C/C++端关键的部分主要是以上这些,接下来就是Java端调用。

首先来看一下so库的加载类,以及C++函数的调用:


package com.yyh.fork;  

  

import java.io.DataInputStream;  

import java.io.DataOutputStream;  

import java.io.File;  

  

public class NativeRuntime {  

  

    private static NativeRuntime theInstance = null;  

  

    private NativeRuntime() {  

  

    }  

      

    public static NativeRuntime getInstance() {  

        if (theInstance == null)  

            theInstance = new NativeRuntime();  

        return theInstance;  

    }  

  

    /**

     * RunExecutable 启动一个可自行的lib*.so文件

     * @date 2016-1-18 下午8:22:28

     * @param pacaageName

     * @param filename

     * @param alias 别名

     * @param args 参数

     * @return

     */  

    public String RunExecutable(String pacaageName, String filename, String alias, String args) {  

        String path = "/data/data/" + pacaageName;  

        String cmd1 = path + "/lib/" + filename;  

        String cmd2 = path + "/" + alias;  

        String cmd2_a1 = path + "/" + alias + " " + args;  

        String cmd3 = "chmod 777 " + cmd2;  

        String cmd4 = "dd if=" + cmd1 + " of=" + cmd2;  

        StringBuffer sb_result = new StringBuffer();  

  

        if (!new File("/data/data/" + alias).exists()) {  

            RunLocalUserCommand(pacaageName, cmd4, sb_result); // 拷贝lib/libtest.so到上一层目录,同时命名为test.  

            sb_result.append(";");  

        }  

        RunLocalUserCommand(pacaageName, cmd3, sb_result); // 改变test的属性,让其变为可执行  

        sb_result.append(";");  

        RunLocalUserCommand(pacaageName, cmd2_a1, sb_result); // 执行test程序.  

        sb_result.append(";");  

        return sb_result.toString();  

    }  

  

    /**

     * 执行本地用户命令

     * @date 2016-1-18 下午8:23:01

     * @param pacaageName

     * @param command

     * @param sb_out_Result

     * @return

     */  

    public boolean RunLocalUserCommand(String pacaageName, String command, StringBuffer sb_out_Result) {  

        Process process = null;  

        try {  

            process = Runtime.getRuntime().exec("sh"); // 获得shell进程  

            DataInputStream inputStream = new DataInputStream(process.getInputStream());  

            DataOutputStream outputStream = new DataOutputStream(process.getOutputStream());  

            outputStream.writeBytes("cd /data/data/" + pacaageName + "\n"); // 保证在command在自己的数据目录里执行,才有权限写文件到当前目录  

            outputStream.writeBytes(command + " &\n"); // 让程序在后台运行,前台马上返回  

            outputStream.writeBytes("exit\n");  

            outputStream.flush();  

            process.waitFor();  

            byte[] buffer = new byte[inputStream.available()];  

            inputStream.read(buffer);  

            String s = new String(buffer);  

            if (sb_out_Result != null)  

                sb_out_Result.append("CMD Result:\n" + s);  

        } catch (Exception e) {  

            if (sb_out_Result != null)  

                sb_out_Result.append("Exception:" + e.getMessage());  

            return false;  

        }  

        return true;  

    }  

  

    public native void startActivity(String compname);  

  

    public native String stringFromJNI();  

  

    public native void startService(String srvname, String sdpath);  

  

    public native int findProcess(String packname);  

  

    public native int stopService();  

  

    static {  

        try {  

            System.loadLibrary("helper"); // 加载so库  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

    }  

  

}


然后,我们在收到开机广播后,启动该服务。


package com.yyh.activity;  

  

import android.content.BroadcastReceiver;  

import android.content.Context;  

import android.content.Intent;  

import android.util.Log;  

  

import com.yyh.fork.NativeRuntime;  

import com.yyh.utils.FileUtils;  

public class PhoneStatReceiver extends BroadcastReceiver {  

  

    private String TAG = "tag";  

  

    @Override  

    public void onReceive(Context context, Intent intent) {  

        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {  

            Log.i(TAG, "手机开机了~~");  

            NativeRuntime.getInstance().startService(context.getPackageName() + "/com.yyh.service.HostMonitor", FileUtils.createRootPath());  

        } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {  

        }  

    }  

  

      

}


Service服务里面,就可以做该做的事情。


package com.yyh.service;  

  

import android.app.Service;  

import android.content.Intent;  

import android.os.IBinder;  

import android.util.Log;  

  

public class HostMonitor extends Service {  

  

    @Override  

    public void onCreate() {  

        super.onCreate();  

        Log.i("daemon_java", "HostMonitor: onCreate! I can not be Killed!");  

    }  

  

    @Override  

    public int onStartCommand(Intent intent, int flags, int startId) {  

        Log.i("daemon_java", "HostMonitor: onStartCommand! I can not be Killed!");  

        return super.onStartCommand(intent, flags, startId);  

    }  

  

    @Override  

    public IBinder onBind(Intent arg0) {  

        return null;  

    }  

}


当然,也不要忘记在Manifest.xml文件配置receiver和service:


receiver  

            android:name="com.yyh.activity.PhoneStatReceiver"  

            android:enabled="true"  

            android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >  

            intent-filter>  

                action android:name="android.intent.action.BOOT_COMPLETED" />  

                action android:name="android.intent.action.USER_PRESENT" />  

            intent-filter>  

        receiver>  

          

        service  android:name="com.yyh.service.HostMonitor"  

                  android:enabled="true"  

                  android:exported="true">  

         service>


run起来,在程序应用里面,结束掉这个进程,不一会了,又自动起来了~~~~跟流氓软件一个样,没错,就是这么贱…



这边是运行在谷歌的原生系统上,Android版本为5.0… 在其他系统下稳定性还远远不足,但是要真正做到杀不死服务几乎是不可能的。 总结一下就是:服务常驻要应对的不是各种难的技术,而是各大ROM。QQ为什么不会被杀死,是因为国内各大ROM不想让他死…


本文主要提供的是一个思路,实现还有诸多不足之处,菜鸟之作,不喜勿喷。


最后附上本例的源代码:Android 通过JNI实现双守护进程

http://download.csdn.net/detail/yyh352091626/9410153


关注「安卓开发精选
看更多精选安卓技术文章
↓↓↓