Lsn19_AM命令源码分析

NDK开发汇总

一 360手机助手之卸载监听

Android系统下列监听方式

  1. 监听系统卸载广播:只能监听到其他应用的卸载广播,无法监听到自己是否被卸载。

ACTION_PACKAGE_REMOVED
ACTION_PACKAGE_REMOVED
皮之不存毛将焉附
内存 --》
监听 别人

  1. 卸载 系统log (正在被安装的包程序不能接收到这个广播), 监听自身

  2. Java线程 轮训 监听 监听/data/data/{package-name}目录是否存在

  3. C进程 监听/data/data/{package-name}目录是否存在 跳转到网页

上述4种方式均不能监听自身的卸载,可以用下面的方式实现

  1. 静默安装另外的apk 监听自己是否被卸载 可以 (root)
监听  /data/data/{package-name}目录是否存在

从前四种方案可以看到,单纯的Java层代码是无法监听自身卸载的。既然Java层无法实现,我们试着使用C语言在底层实现。

实现方式

借助Linux进程fork出来的C进程在应用被卸载后不会被销毁,监听/data/data/{package-name}目录是否存在,如果不存在,就证明应用被卸载了。

  1. fork()子进程
  2. 创建监听文件
  3. 初始化inotify实例
  4. 注册监听事件
  5. 调用read函数开始监听
  6. 卸载反馈统计

加载

init native
android-6.0.0_r1\frameworks\base\core\jni
//初始化监听
private native int init();
private native int startWatching(int fd, String path, int mask);

fork(); 开两个进程
一个函数 1

  一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。
  然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

它是一个内核用于通知用户空间程序文件系统变化的机制。

结构中的 wd 为被监视目标的 watch 描述符,
mask 为事件类型
len 为 name字符串的长度
name 为被监视目标的路径名,该结构的 name 字段为一个桩
它只是为了用户方面引用文件名,文件名是变长的,

buf 是一个 inotify_event 结构的数组指针,
BUF_LEN 指定要读取的总长度,
buf 大小至少要不小于 BUF_LEN,
该调用返回的事件数取决于 BUF_LEN 以及事件中文件名的长度
。Len 为实际读去的字节数,即获得的事件的总长度。

IN_ACCESS,即文件被访问
IN_MODIFY,文件被 write
IN_ATTRIB,文件属性被修改,如 chmod、chown、touch 等
IN_CLOSE_WRITE,可写文件被 close
IN_CLOSE_NOWRITE,不可写文件被 close
IN_OPEN,文件被 open
IN_MOVED_FROM,文件被移走,如 mv
IN_MOVED_TO,文件被移来,如 mv、cp
IN_CREATE,创建新文件
IN_DELETE,文件被删除,如 rm
IN_DELETE_SELF,自删除,即一个可执行文件在执行时删除自己
IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己
IN_UNMOUNT,宿主文件系统被 umount
IN_CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE,文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)

注:上面所说的文件也包括目录。

作业
#include <stdio.h>
int main(int argc, char* argv[]) {
fork();
fork() && fork() || fork();
fork();

} 求 进程 数量

Intent

  am start -n com.yuanhh.app/.MainActivity

am 不需要弹选择框

主要代码

#include <jni.h>
#include <string>
#include <sys/inotify.h>
#include <fcntl.h>
#include <android/log.h>
#include <malloc.h>
#include <unistd.h>
#define LOG_TAG "tuch"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C"
{




JNIEXPORT void JNICALL
Java_com_dongnao_ls19uninstall_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject obg,jint sdk,jstring path) {
//    pid_t pid=fork();
//    if (pid < 0) {
//        LOGD("fork失败");
////        系统fork()
//    } else if (pid > 0) {
//        LOGD("父进程");
//    } else{
//        LOGD("子进程");
//        //    初始化  inotify
//
//        int observer = open(observerFile, O_RDONLY);
//        if (observer == -1) {
//            //不存在就创建
//            observer = open(observerFile, O_CREAT);
//        }
//        int fileDescriple = inotify_init();
//        int watch=inotify_add_watch(fileDescriple, observerFile, IN_DELETE_SELF);
//        if (watch < 0) {
//            LOGD("监听失败");
//        }
//        void *p_buf=malloc(sizeof(struct inotify_event));
//        //        阻塞式函数  anr
//        size_t readBytes=read(fileDescriple,p_buf, sizeof(struct inotify_event));
//// 主进程   1
////        执行到下面来了    文件发生了改变  用户卸载了 app
//        LOGD("监听类型 %d    ,%d",((struct inotify_event *) p_buf)->mask,IN_DELETE_SELF);
//        if (((struct inotify_event *) p_buf)->mask == IN_DELETE_SELF) {
//////                覆盖安装
////                FILE *app_file = fopen("/data/data/com.dongnao.ls19uninstall", "r");
////            if (app_file == NULL) {
////                //   删除app   移除监听
////                inotify_rm_watch(fileDescriple, watch);
////            } else{
////                //   覆盖安装    重新进行监听
////                fclose(app_file);
////                FILE *p_observelFile = fopen(observerFile, "w");
////                int watchDescip=inotify_add_watch(fileDescriple, observerFile, IN_DELETE_SELF);
////            }
//            }
//        LOGD("跳转网页");
////        铁了心要删除app  sdk   17   am  设置到环境变量   多用户的操作
//            if (sdk < 17) {
//                execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d",
//                       "http://www.baidu.com",NULL);
//
//            } else{
//                execlp("am", "am", "start","--user","0","-a", "android.intent.action.VIEW", "-d",
//                       "http://www.baidu.com",NULL);
//            }
//
//    }

}

JNIEXPORT void JNICALL
Java_com_dongnao_ls19uninstall_MainActivity_load__ILjava_lang_String_2(JNIEnv *env,
                                                                       jobject instance, jint sdk,
                                                                       jstring path_) {
    const char *path = env->GetStringUTFChars(path_, 0);
    pid_t pid=fork();
    if (pid < 0) {
        LOGD("fork失败");
//        系统fork()
    } else if (pid > 0) {
        LOGD("父进程");
    } else {
        LOGD("子进程");
        //    初始化  inotify
        int fileDescriple = inotify_init();
        int watch=inotify_add_watch(fileDescriple, path, IN_DELETE_SELF);
        void *p_buf=malloc(sizeof(struct inotify_event));
        //        阻塞式函数  anr
        size_t readBytes=read(fileDescriple,p_buf, sizeof(struct inotify_event));
        inotify_rm_watch(fileDescriple, watch);
        LOGD("跳转网页");
//        铁了心要删除app  sdk   17   am  设置到环境变量   多用户的操作
        if (sdk < 17) {
            execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d",
                   "http://www.baidu.com",NULL);

        } else{
            execlp("am", "am", "start","--user","0","-a", "android.intent.action.VIEW", "-d",
                   "http://www.baidu.com",NULL);
        }
    }

    // TODO

    env->ReleaseStringUTFChars(path_, path);
}


}

二 AM

● -a : 指定Intent action, 实现原理Intent.setAction();
● -n : 指定组件名,格式为{包名}/.{主Activity名},实现原理Intent.setComponent();
● -d <DATA_URI>: 指定Intent data URI
● -t <MIME_TYPE>: 指定Intent MIME Type
● -c [-c ] …]:指定Intent category,实现原理Intent.addCategory()
● -p : 指定包名,实现原理Intent.setPackage();
● -f : 添加flags,实现原理Intent.setFlags(int ),紧接着的参数必须是int型;

基本类型
参数-e/-es-esn-ez-ei-el-ef-eu-ecn类型String(String)nullbooleanintlongfloaturicomponent
比如参数es是Extra String首字母简称,实例:
intent.putExtra(“website”,“website gityuan.com”)
am start -n com.dongnao.app/.MainActivity -es website gityuan.com

intent.put

比如参数efal,是Extra float Array List首字母简称,多个value值之间以逗号隔开,实例:
am start -n comdongnao.app/.MainActivity -efal nums 1.2,2.2
此处-es website gityuan.com,等价于Intent.putExtra(“website”, “gityuan.com”);

AM四大组件 所有跳转问题
AM 命令
跳转 模块

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章