Android NDK development (8)-uninstall the app listening itself, pop up user feedback survey, androidndk

Source: Internet
Author: User
Tags inotify

Android NDK development (8)-uninstall the app listening itself, pop up user feedback survey, androidndk

Reprinted please indicate the source:Http://blog.csdn.net/allen315410/article/details/42521251

Analysis of listening and uninstalling scenarios and Principles 1. Scenario Analysis

In my previous blog, I wrote about the NDK development practice project, using the open-source LAME library to transcode MP3, which is used as a deep understanding of the previous basic blogs. However, such a project is of little use, in addition to NDK skills. This blog will describe a very common feature of the next major application. It is also a small Demo of the Android application developed based on JNI. After reading this, this Demo not only improves the understanding of NDK development, but also can be used in actual development. I don't know if you are using an Android app. When we Uninstall this app, a webpage "user feedback survey" will pop up on the device, maybe many people have not paid attention to it or ignored it directly. From now on, please pay attention to it. You may wish to download and uninstall the applications such as "pea pod" and "360, check whether the browser is displayed on the device and the "XXX user feedback" is displayed on the browser "? I wrote some HTML forms and asked, "Are you sure you want to uninstall such a good application ?" "Where did we offend you ?" "After uninstallation, are you still installing it ?", A joke. The actual effect is as follows:


Well, the picture above seems to have been shown? How can we implement such a small function? First, we will analyze the Java layer based on our Android:

1. Listen to the unmounted broadcast of the system, but this can only listen to the unmounted broadcast action of other applications. By uninstalling the broadcast listener, the listener itself cannot listen: Failed
2. In the system configuration file, it is unreasonable to mark whether the application is uninstalled and judge whether the tag is used to show user feedback, because after the application is uninstalled, the configuration file is gone.
3. Silently install another program and listen to the uninstalling action of your application. The premise is to be root. However, most mobile phones in the market do not have the root permission by default.
4. Service detection can only be enabled by yourself. When the service is uninstalled, the service is also killed.

None of the above seems to be able to implement this function. Indeed, this is not possible simply from the Java layer.


2. The above situation analysis shows that Java cannot implement such a function. Should you consider using JNI, at the underlying layer, we can use C to enable such a built-in browser to load user feedback pages. Before Knowing this method, we need to understand the following knowledge points.

1. Use the c language and c process for monitoring.

Since Java cannot do this, we try to use the C language at the underlying level to enable the C language to call the Android adb command to open the built-in browser.

Determine whether you are uninstalled
When the andoird program is installed, a directory named/data/package name is generated under the/data/directory.
Monitor whether the directory still exists. If it does not exist, the application is uninstalled.


2. c code can copy the current process as its son. When the parent process is destroyed, the child process still exists.

Fork () function:

 The fork () function creates a process that is almost identical to the original process through system calls. The two processes can do the same thing, which means they have a son, if the initial parameters or input parameters are different, the two processes do different things. After the fork function is called by the current process, the system allocates resources to the current process, and then copies the values of all the variables of the current process to the new process (only a few values are different), which is equivalent to cloning itself.

Before pid_t fpid = fork () is called, a process executes the code. After this statement is executed, two processes execute the code. The execution of the two processes is not in a fixed order, it mainly depends on the System Scheduling Policy. The fork function is called once, but can return two or even three results.
(1) return the child process id (pid) in the parent process)
(2) return 0 in the sub-process
(3) If an error occurs, a negative value smaller than 0 is returned.
Cause of error: (1) the number of processes has reached the system limit (2) the memory is insufficient.


3. Check whether the parent process is uninstalled in the sub-process of code c. If the sub-process is uninstalled, notify the Android system to open a url and uninstall the web page under investigation.

AM command

The adb tool provided by the Android system executes the adb shell on the basis of the adb to directly execute the shell command on the android system.
Am command: the Android system uses the adb shell to start an Activity, Service, call, start a browser, and Other Android commands.
The am command source code is in Am. in java, executing the am command in the shell environment actually starts a thread to execute Am. in java, the main function (main method), parameters followed by the am command will be passed to the main function as runtime parameters, mainly implemented in Am. java run method.
The am command can use the start sub-command and the specified parameter. start is a sub-command, not a parameter.
Common parameters:-a: indicates the action,-d: indicates the data carried,-t: indicates the input type, and-n: Specifies the component name.

For example, if we enter adb shell in command line mode, use this command to open a webpage


Similar Commands include:

Call
Command: am start-a android. intent. action. CALL-d tel: phone number
Example: am start-a android. intent. action. CALL-d tel: 10086

Open a webpage
Command: am start-a android. intent. action. VIEW-d URL
Example: am start-a android. intent. action. VIEW-d http://www.baidu.com

Start a service

Command: am startservice <service name>
Example: am startservice-n com. android. music/com. android. music. MediaPlaybackService


Execlp () function

Execlp functions are functions that execute system commands in C language.
Execlp () searches for the file name that matches the parameter file from the directory indicated by the PATH environment variable, and then runs the file, then, the second parameter is used as the argv [0], argv [1],..., the last parameter must end with a NULL pointer.
In android development, the path of the execlp function to android is in the system/bin/directory.

Call format:

Execlp ("am", "am", "start", "-- user", "0", "-a", "android. intent. action. VIEW,-d, http://shouji.360.cn/web/uninstall/uninstall.html, (char *) NULL );

========================================================== ========================================================== ==========================================


Coding Implementation 1. Java layer defines the native METHOD

Defines an native method at the Java layer and provides calls at the Java and C ends.

public native void uninstall(String packageDir, int sdkVersion);

This method needs to pass the installation directory of the application and the version number of the current device, get it in Java code, and pass it to C code for processing.


2. Use the javah command to generate the method signature header file

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_appuninstall_MainActivity */#ifndef _Included_com_example_appuninstall_MainActivity#define _Included_com_example_appuninstall_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_appuninstall_MainActivity * Method:    uninstall * Signature: (Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_com_example_appuninstall_MainActivity_uninstall  (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif

After the method signature is generated, right-click the project and choose Android Tools> Add Native Support. In the displayed dialog box, enter the edited C/C ++ file name, find the cpp extension file in the jni directory automatically generated by the project and change it. c extension file, because this case is based on the c language, and then modify the Android. the LOCAL_SRC_FILES In the mk file is. c file. copy the signature file in method h to the jni directory.


3. Write C code

As analyzed in the above principle, we cannot implement such a function using Java. We can only clone a sub-process of the current App in C, let this sub-process listen to the uninstallation of the application itself. So What steps do we need to implement such a function? The following describes how to write code:

1. Convert the passed java package name into a c string
2. Create a clone process of the current process
3. Perform different operations based on the returned values.
4. Monitor the/data/package name directory in the sub-process
5. If the directory is deleted, it indicates it is uninstalled and the user feedback page is displayed.

# Include <stdio. h> # include <jni. h> # include <malloc. h> # include <string. h> # include <strings. h> # include <stdlib. h> # include <unistd. h> # include "com_example_appuninstall_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 ** indicates the first address of the char array * Jstring2CStr converts the jstring type in java into a char string */char * Jstring2CStr (JNIEnv * env, jstring jstr) {char * rtn = NULL; jclass clsstring = (* env)-> FindClass (env, "java/lang/String "); // Stringjstring strencode = (* env)-> NewStringUTF (env, "GB2312"); // obtain 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 ); // "\ 0" memcpy (rtn, ba, alen); rtn [alen] = 0;} (* env)-> ReleaseByteArrayElements (env, barr, ba, 0 ); // return rtn;} JNIEXPORT void JNICALL Java_com_example_appuninstall_MainActivity_uninstall (JNIEnv * env, jobject obj, jstring packageDir, jint sdkVersion) {// 1, convert the passed java package name to the c string char * pd = Jstring2CStr (env, packageDir); // 2, create the clone process pid_t pid = fork () of the current process (); // 3. Perform different operations based on the returned values. <0,> 0, = 0if (pid <0) {// indicates that the clone process failed LOGD ("current crate process failure");} else if (pid> 0) {// indicates that the clone process succeeded, and the code runs in the parent process LOGD ("crate process success, current parent pid = % d", pid);} else {// indicates that the clone process is successful, and the code runs in the sub-process LOGD ("crate process success, current child pid = % d", pid); // 4, monitoring/data/package name in the sub-process while (JNI_TRUE) {FILE * file = fopen (pd, "rt"); if (file = NULL) {// The application is uninstalled and the system is notified to open the user feedback page LOGD ("app uninstall, current sdkversion = % d", sdkVersion); if (sdkVersion> = 17) {// The Android4.2 system supports multi-user operations, so you must specify the user execlp ("am", "am", "start", "-- user", "0 ", "-a", "android. intent. action. VIEW ","-d "," http://www.baidu.com ", (char *) NULL);} else {// versions earlier than Android4.2 do not need to specify the user execlp (" am ", "am", "start", "-a", "android. intent. action. VIEW ","-d "," http://www.baidu.com ", (char *) NULL) ;}} else {// The application is not uninstalled LOGD (" app run normal ");} sleep (1 );}}}
The above code is implemented using C code like the above steps. The first thing to note is the Android version. As we all know, Android is a very good Linux-based operating system, in addition, Android and later versions support multi-user operations, but this also brings inconvenience to our small project, when executing the am command in multiple users, it is unnecessary to specify a user and a number, therefore, when writing C code, we need to differentiate the Android system version and execute the corresponding am commands respectively. We can implement the SDK for obtaining the Android system version at the Java layer, then it is passed as a parameter to the C code. The C code executes the am Command Based on the Android version.

NOTE: For the sake of convenience, I used a While (true) endless loop when the C Code monitors whether the application is uninstalled, and performed monitoring detection once every 1 ms, the code written in this way is "not environmentally friendly". The result is that the program is continuously executed and logs are constantly printed, which will inevitably result in the waste of cpu computing resources and power consumption. The best solution is to use the FileObserve file observer provided by Android to us. FileObserve uses the inotify process in the Linux system to monitor changes in the file directory, this API is required for optimization in this instance, but more knowledge is required. For the sake of simple demonstration, the while (true) endless loop is used for the moment, for the later optimized version, I will write it out and publish it together!


4. Compile the. so dynamic library.

As written in the previous blog, after we have compiled the C source code, we need to use the ndk-build command to compile it. so file, the specific compilation process is also very simple, switch to the C/C ++ editor in Eclipse, find the "Little Hammer" button, click it to start compilation, if no error occurs in the Code, the compiled result is as follows:



5. Write Java code, pass data, and load the Linked Library.

The above work is done, and the rest is to load the Link Library in Java, and call this local method. First, obtain the directory/data/package name installed in this application, obtain the version number of the current device, send it to the local method, and finally call this method.

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);}}
6. Test

Okay, the application is finished. Let's clean the project, start an ARM-based simulator, run the program, return to the desktop, click the application image -- uninstall the application, and see the effect:


Well, let's take a look at the results. In fact, the webpage should be a user feedback survey page. Because I have no server, I directed the website to the Baidu homepage. during development, you can change the parameter URL in the execlp function to your server URL. Check Log output:


As you can see, the LOG input LOG is consistent with the Code process. Now, the source code is under the link below. If you are interested, you can download the research. You are welcome to give me your valuable comments, let's learn and make progress together!

After querying the information, I have learned how to use the Linux Inotify mechanism to listen to the installation directory of the application without using the while (true) Polling method. The latest optimized version has been completed, click here to view the implementation principle and code: Android NDK Development (9) -- uninstall and upgrade the app listening version, and use Inotify to monitor the installation directory


Download the source code here


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.