After the Android Application is uninstalled, the specified connection is automatically opened in the browser.
This document describes how to automatically open a specified connection in a browser after an Android Application is uninstalled.
Principle: In the android program somewhere, call C code based on JNI to enable a sub-process to monitor the file directory of the application in the system. Once the application is uninstalled, the directory will be deleted by the system, at this time, the sub-process is triggered to execute the relevant code (this example calls the browser to execute and open a connection)
1. Create a jni directory under the android Project
2. Create the file observer. c In the jni directory.
/** Copyright (C) 2009 The Android Open Source Project ** Licensed under the Apache License, Version 2.0 (the "License "); * you may not use this file before t in compliance with the License. * You may be obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "as is" BASIS, * without warranties or conditions of any kind, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/# include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
/* Macro definition begin * // clear 0 macro # define MEM_ZERO (pDest, destSize) memset (pDest, 0, destSize) // LOG macro definition # define LOG_INFO (tag, msg) _ android_log_write (ANDROID_LOG_INFO, tag, msg) # define LOG_DEBUG (tag, msg) _ android_log_write (ANDROID_LOG_DEBUG, tag, msg) # define LOG_WARN (tag, msg) _ android_log_write (ANDROID_LOG_WARN, tag, msg) # define LOG_ERROR (tag, msg) _ android_log_write (ANDROID_LOG_ERROR, tag, msg)/* global variable begin */Static char c_TAG [] = "onEvent"; static jboolean B _IS_COPY = JNI_TRUE;/* expose the natvie Method */jstring encode (JNIEnv * env, jobject thiz, jstring path, jstring url, jint version) {jstring tag = (* env)-> NewStringUTF (env, c_TAG); // initialize log LOG_DEBUG (* env) -> GetStringUTFChars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env)-> NewStri NgUTF (env, "init OK"), & B _IS_COPY); // fork sub-process to run the polling task pid_t pid = fork (); if (pid <0) {// Error log LOG_ERROR (* env)-> GetStringUTFChars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env) -> NewStringUTF (env, "fork failed !!! "), & B _IS_COPY);} else if (pid = 0) {// subprocess registration directory listener int fileDescriptor = inotify_init (); if (fileDescriptor <0) {LOG_DEBUG (* env)-> GetStringUTFChars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env)-> NewStringUTF (env, "inotify_init failed !!! "), & B _IS_COPY); exit (1);} int watchDescriptor; watchDescriptor = inotify_add_watch (fileDescriptor, (* env)-> GetStringUTFChars (env, path, NULL ), IN_DELETE); if (watchDescriptor <0) {LOG_DEBUG (* env)-> GetStringUTFChars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env)-> NewStringUTF (env, "inotify_add_watch failed !!! "), & B _IS_COPY); exit (1) ;}// allocate the cache to read the event. The cache size = the size of a struct inotify_event, in this case, an event void * p_buf = malloc (sizeof (struct inotify_event); if (p_buf = NULL) {LOG_DEBUG (* env)-> GetStringUTFChars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env)-> NewStringUTF (env, "malloc failed !!! "), & B _IS_COPY); exit (1) ;}// start listening to LOG_DEBUG (* env)-> GetStringUTFChars (env, tag, & B _IS_COPY), (* env) -> GetStringUTFChars (env, (* env)-> NewStringUTF (env, "start observer"), & B _IS_COPY); // read will block the process, size_t readBytes = read (fileDescriptor, p_buf, sizeof (struct inotify_event); // when you go to this page, you will receive the directory deletion event, deregister the listener free (p_buf), inotify_rm_watch, IN_DELETE); // The directory does not contain log LOG_DEBUG (* env)-> GetStringUTFC Hars (env, tag, & B _IS_COPY), (* env)-> GetStringUTFChars (env, (* env)-> NewStringUTF (env, "uninstalled"), & B _IS_COPY )); if (version> = 17) {// because the user permission management is stricter, add -- user 0 execlp ("am", "am", "start ", "-- user", "0", "-a", "android. intent. action. VIEW ","-d ", (* env)-> GetStringUTFChars (env, url, NULL), (char *) NULL);} else {execlp (" am ", "am", "start", "-a", "android. intent. action. VIEW ","-d ", (* env )-> GetStringUTFChars (env, url, NULL), (char *) NULL);} // Extension: other shell commands, am (activity manager ), you can open a program, service, broadcast intent, and so on} else {// The parent process exits directly, so that the child process is adopted by the init process to prevent the child process from freezing} return (* env) -> NewStringUTF (env, "Hello from JNI! ");}
3. Create the Android. mk file in the jni directory.
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:=observerLOCAL_SRC_FILES:=observer.cLOCAL_C_INCLUDES:= $(LOCAL_PATH)/includeLOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lloginclude $(BUILD_SHARED_LIBRARY)
4. Create the natvie method and call the JNI method in Android.
Package com. zgy. catchuninstallself; public class UninstallObserver {static {System. loadLibrary ("observer");} public static native String startWork (String path, String url, int version); // path: data/[packageNmae]; url: the page to jump to. It must start with http: // or https}
String url = "http://www.baidu.com";UninstallObserver.startWork(path, url, android.os.Build.VERSION.SDK_INT);
Note: When the JNI method is repeatedly called, I did not test whether multiple sub-processes will be enabled again. This is left for testing.