Android NDK Development (ix)--Application monitoring itself uninstall upgrade, use INotify to monitor the installation directory

Source: Internet
Author: User
Tags inotify ibm developerworks

Reprint Please specify source:http://blog.csdn.net/allen315410/article/details/42555415

In the previous blog, we talked about a small case, using the NDK listener application itself to unload, and open the built-in browser to load the user invocation page. The principle and implementation of the monitoring application itself uninstall can be found in the previous blog, the address is: http://blog.csdn.net/allen315410/article/details/42521251, here will not repeat.

It is noteworthy that in the previous blog I have also quoted a case of the problem, that is, when listening to the application installation directory is deleted, use a while (true) such a dead loop, so that C code every 1 seconds to automatically check whether the application installation directory exists, This effect is completely achievable, but the drawbacks are also obvious, because the use of the dead loop, so that the code is not environmental protection, the inevitable repeated execution, repeat print log, CPU computing resources, this is a bad solution.

Here, I would like to introduce a better solution, is to use a Linux system kernel features--inotify, to monitor the application installation directory changes, Inotify is a file system change notification mechanism, such as file additions, deletions and other events can immediately let the user state to know, This mechanism is to compensate for the lack of Linux system in the desktop domain, was added in the linux2,.6 kernel, it is fortunate that our great Android system is built on the basis of the Linux2.6 kernel, so Android also contains the inotify mechanism.


About INotify:

in the user state, INotify is used by three system calls and file I/O operations on the returned file descriptor, and the first step in using INotify is to create the INotify instance:

int fd = Inotify_init ();
each inotify instance corresponds to a separate sorted queue.

File system Change event is called a watches object management, each watch is a two-tuple (target, event mask), the target can be a file or directory, the event mask represents the INotify event that the application wants to focus on, and each bit corresponds to a inotify event. The Watch object is referenced by the watch descriptor and watches is added through the path name of the file or directory. Directory watches will return events that occurred above all the files in that directory.
The following function is used to add a watch:

int wd = Inotify_add_watch (fd, path, mask);
FD is the file descriptor returned by Inotify_init (), path is the pathname of the target being monitored (that is, the file name or directory name), mask is the event mask, and the event represented by each bit is defined in the header file Linux/inotify.h. You can modify the event mask in the same way, changing the INotify event that you want to be notified. Wd is the watch descriptor.

The following are the optional values for the mask event masks:

In_access, that is, the file is accessed
In_modify, File is write
In_attrib, file attributes are modified, such as chmod, chown, touch, etc.
In_close_write, writable file is CLOSE
In_close_nowrite, non-writable files are CLOSE
In_open, File is OPEN
In_moved_from, files are removed, such as MV
In_moved_to, files are moved, such as MV, CP
In_create, creating a new file
In_delete, files are deleted, such as RM
In_delete_self, self-deletion, that is, an executable file deletes itself when executed
In_move_self, self-moving, that is, an executable file moves itself at execution time
In_unmount, the host file system is Umount
In_close, file is closed, equivalent to (In_close_write | In_close_nowrite)
In_move, file is moved, equivalent to (In_moved_from | IN_MOVED_TO)
Note: The above mentioned files also include directories.


The following function is used to delete a watch:

int ret = Inotify_rm_watch (FD, WD);
FD is the file descriptor returned by Inotify_init (), and WD is the watch descriptor returned by Inotify_add_watch (). Ret is the return value of a function.
A file event is represented by a inotify_event structure, which is obtained by using the usual file read function read for the file descriptor returned by Inotify_init ():

struct Inotify_event {        __s32           wd;             /* Watch Descriptor */        __u32           mask;           /* Watch Mask */        __u32           cookie;         /* Cookie to synchronize the events */        __u32           len;            /* Length (including nulls) of the name */        char            name[0];        /* Stub for possible name */};
The WD in the structure is the watch descriptor for the monitored target, mask is the event mask, Len is the length of the name string, name is the path name of the monitored target, the name field of the structure is a pile, it simply refers to the user aspect of the file name, the file name is variable length, It is actually immediately following the structure, and the file name is populated with 0 to enable the next event structure to be 4-byte aligned. Note that Len also counts the number of padding bytes.
Multiple events can be obtained at one time through a read call, provided the BUF is large enough.

size_t len = Read (FD, buf, Buf_len);
buf is an array pointer to a inotify_event structure, Buf_len specifies the total length to read, the BUF size is at least less than Buf_len, and the number of events returned by the call depends on the Buf_len and the length of the file name in the event. Len is the number of bytes actually read, which is the total length of the obtained event.
You can use Select () or poll () on the file descriptor FD returned by the function inotify_init (), or you can use the IOCTL command fionread on FD to get the length of the current queue. Close (FD) deletes all watch added to the FD and does the necessary cleanup.

int inotify_init (void); int inotify_add_watch (int fd, const char *path, __u32 mask); int inotify_rm_watch (int fd, __U32 m ASK);
Note: The above data refer to IBM DEVELOPERWORKS,IBM Developerworks is a very excellent technical learning, we can find a lot of good information to learn, if you want to know more about the inotify mechanism, please click http:// www.ibm.com/developerworks/cn/linux/l-inotifynew/


Code implementation:

About the code, most can refer to the previous blog case code, because most of the code and configuration files and compilation steps in the previous blog and write more detailed, here is not repeated writing, the only part of the change is that the C code in the while (true) dead loop part of the deletion, Change to use the inotify mechanism to listen for changes in the application directory:

Compiled header file:

/* Don't EDIT this file-it are machine generated */#include <jni.h>/* Header for class Com_example_appuninstalldem O_mainactivity */#ifndef _included_com_example_appuninstalldemo_mainactivity#define _included_com_example_ Appuninstalldemo_mainactivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_appuninstalldemo_ Mainactivity * Method:    Uninstall * Signature: (ljava/lang/string;i) V */jniexport void Jnicall Java_com_example_ Appuninstalldemo_mainactivity_uninstall  (jnienv *, Jobject, jstring, jint); #ifdef __cplusplus} #endif #endif
C's Code implementation:

#include <stdio.h> #include <jni.h> #include <malloc.h> #include <string.h> #include < strings.h> #include <stdlib.h> #include <unistd.h> #include <sys/inotify.h> #include <fcntl.h > #include <stdint.h> #include "com_example_appuninstalldemo_mainactivity.h" #include <android/log.h> #define LOG_TAG "system.out.c" #define LOGD (...) __android_log_print (Android_log_debug, Log_tag, __va_args__) #define Logi (...) __android_log_print (Android_log_info, Log_tag, __va_args__)/** * Return value char* This represents the first address of the char array * JSTRING2CSTR Convert the type of jstring in Java into a char string in the C language */char* jstring2cstr (jnienv* env, jstring jstr) {char* Rtn = Null;jclass clsstring = ( *ENV)->findclass (env, "java/lang/string"); Stringjstring Strencode = (*env)->newstringutf (env, "GB2312"); Get a Java string "GB2312" jmethodid mid = (*env)->getmethodid (env, clsstring, "GetBytes", "(ljava/lang/string;) [B");// [String.getbytes ("gb2312"); Jbytearray Barr = (Jbytearray) (*env)->callobjectMethod (env, JSTR, Mid,strencode); String. GetByte ("GB2312"); Jsize alen = (*env)->getarraylength (env, Barr); The length of the byte array jbyte* ba = (*env)->getbytearrayelements (env, Barr, Jni_false); if (Alen > 0) {rtn = (char*) malloc (Alen + 1); "memcpy" (RTN, BA, Alen); Rtn[alen] = 0;} (*env)->releasebytearrayelements (env, Barr, BA, 0); return RTN;} Jniexport void Jnicall Java_com_example_appuninstalldemo_mainactivity_uninstall (jnienv * env, jobject obj, jstring Packagedir, Jint sdkversion) {///1, converts the package name of the passed-in Java to the C string char * PD = JSTRING2CSTR (env, packagedir);//2, creating the clone process of the current process pid_t pi d = fork ();//3, depending on the return value, do different operations, &LT;0,&GT;0,=0IF (PID < 0) {//indicates that the cloning process failed logd ("Current crate process Failure");} else if ( PID > 0) {//Indicates the cloning process was successful, and the code runs in the parent process LOGD ("Crate process success,current Parent PID =%d", pid);} else {//Indicates the cloning process was successful and the code runs In the subprocess logd ("Crate process success,current child pid =%d", pid);//4, monitor the/data/data/package name in the child process this directory//initialize the inotify process int FD = Inotif Y_init (); if (FD < 0) {LOGD ("Inotify_init Failed!!! "); Exit (1);} Add inotify Listener int wd = Inotify_add_watch (FD, PD, In_delete), if (WD < 0) {logd ("Inotify_add_watch failed!!!"); Exit (1);} Allocates the cache so that the event is read, the cache size = the size of a struct inotify_event, such that a eventvoid *p_buf = malloc (sizeof (struct inotify_event)) is processed at a time; P_buf = = NULL) {logd ("malloc failed!!!"); Exit (1);} Start monitoring LOGD ("Start Observer"), ssize_t readbytes = Read (FD, p_buf,sizeof (struct inotify_event)),//read blocks the process, Go here to show the event that the directory was deleted, Logout listener free (P_BUF), Inotify_rm_watch (FD, in_delete);//The application was uninstalled, the notification system opened the user Feedback page logd ("app Uninstall, Current sdkversion =%d ", sdkversion), if (sdkversion >=) {//Android4.2 system supports multi-user operation after, so specify user EXECLP (" AM "," AM "," start ","--user "," 0 ","-a "," Android.intent.action.VIEW ","-D "," http://www.baidu.com ", (char*) NULL);} else {//Android4.2 Previous versions do not need to specify user EXECLP ("AM", "AM", "Start", "-a", "Android.intent.action.VIEW", "-D", "/http Www.baidu.com ", (char*) NULL);}}}
Code as shown above, you can according to the above INotify introduction and code in the comments, the implementation of the code is basically not difficult, but understand the implementation of the principle of a good understanding of the inotify implementation mechanism, so as to be more effective AH.

Java layer code is simple, look directly at:

public class Mainactivity extends Activity {static {system.loadlibrary ("Uninstall");} public native void Uninstall (String packagedir, int sdkversion), @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); String Packagedir = "/data/data/" + getpackagename (); int sdkversion = Android.os.build.version.sdk_int;uninstall ( Packagedir, sdkversion);}}

To uninstall the application after running, the effect is as follows:



Please download the source code here


Android NDK Development (ix)-application monitoring itself uninstall upgrade, use INotify to monitor the installation directory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.