Android implements bsdiff function based on NDK
Prepare
Download the required C file and decompress it directly
bsdiff
bzip(bsdiff dependency library)
The required files have been downloaded by the project prepare directory
Project creation
Studio new c++ project
1. Unzip bzip to src/main/cpp/bzip directory (you can delete files that are not .c or .h, and keep the file reference project)
2. Unzip bsdiff to src/main/cpp/ directory
3. Configuration
#Related bzip directory
file(GLOB bzip bzip/*.c)
#Add c/c++ libraries that need to participate in the compilation
add_library( # Sets the name of the library.
patch # default native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${bzip}
# default
)
#Include the bzip directory, no need to write the package path
include_directories(bzip)
4. Create tool classes
public class PatchUtil {
static {
("patch"); // default native-lib
}
public static native int bsPatch(String old, String patch, String output);
public static native int bsDiff(String old, String newfile, String patch);
}
Use the shortcut key ALT+ENTER to automatically generate jni methods
5. Implement bsdiff and bspatch functions
// Declare external c methods, bsdiff, and bspatch have main methods, remember to change them to different method names
extern "C" {
extern int main(int argc, const char *argv[]);
extern int diff_main(int argc, const char *argv[]);
}
extern "C" JNIEXPORT jint JNICALL
Java_me_leon_patch_PatchUtil_bsDiff(JNIEnv *env, jclass thiz, jstring old, jstring newfile_,jstring patch_) {
// Turn jstring to char * because the parameters of bspatch need to be
const char *oldApk = env->GetStringUTFChars(old, 0);
const char *newFile = env->GetStringUTFChars(newfile_, 0);
const char *output = env->GetStringUTFChars(patch_, 0);
// Call bsDiff c method
const char *argv[] = {"", oldApk, newFile, output};
int r = diff_main(4, argv);
// jstring release
// C/C++ does not have the gc function of java, and resources need to be manually released
env->ReleaseStringUTFChars(old, oldApk);
env->ReleaseStringUTFChars(newfile_, newFile);
env->ReleaseStringUTFChars(patch_, output);
return r;
}
extern "C" JNIEXPORT jint JNICALL
Java_me_leon_patch_PatchUtil_bsPatch(JNIEnv *env, jclass thiz, jstring old,
jstring patch_,
jstring output_) {
// Turn jstring to char *
const char *oldApk = jstringToChar(env, old);
const char *patch = jstringToChar(env, patch_);
const char *output = jstringToChar(env, output_);
// Call bsPatch c method
const char *argv[] = {"", oldApk, output, patch};
int r = main(4, argv);
// Resource Release
env->ReleaseStringUTFChars(old, oldApk);
env->ReleaseStringUTFChars(patch_, patch);
env->ReleaseStringUTFChars(output_, output);
return r;
}
6. Compile and run the code
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
Reason: In the higher version of ndk, the default abiFilters is armeabi-v7a
Solution: Add in module defaultConfig closure
ndk{
abiFilters "arm64-v8a","armeabi-v7a","x86","x86_64"
}
7. After the compilation is successful, write a test program and test the two methods of PatchUtil
Please implement the page and functions by yourself, add two Buttons to realize the PatchUtil function
If you use an app or demo, please prepare the test file first.
adb push /sdcard/
adb push /sdcard/
8. Read permissions for manifest file configuration file (higher versions require dynamic authorization)
<uses-permission android:name=".WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name=".READ_EXTERNAL_STORAGE" />
<uses-permission android:name=".REQUEST_INSTALL_PACKAGES"/>
9. Test
The return result is 0, which means success. You can use the adb command to view the file status.
adb shell
cd /sdcard
ll
Encapsulate lib for others to use
- Call the gradle command to generate the so library
graldew build
- Create a new Android lib project, with the same package name as C++ project
- copy
- Copy all folders under \build\intermediates\merged_native_libs\release\out\lib to src/main/jniLibs
- Use (refer to the use of demo)
- Introduced through implementation project
- You can also upload it to jcenter or maven private server and implementaion directly
Attached with a personal package and test library:
implementation 'me.leon406:patch:1.0.1'
#If it cannot be used, please add it to the project repositories closure
#maven {url "/leon4062/maven"}
Project address: /Leon406/Patch
refer to:
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
Android incremental update (used by bsdiff)