Android NDK开发之旅16--NDK--文件拆分与合并
16lz
2021-01-23
Android NDK开发之旅 目录
1.JNI声明文件
package com.haocai.ndktest;/** * Created by Xionghu on 2017/11/9. * Desc: */public class NDKFileUtils { /** * 拆分 * @param path 完整包路径 * @param path_pattern 分包路径 * @param count */ public native static void diff(String path,String path_pattern,int count); /** * 合并 * @param path_pattern 分包路径 * @param count * @param merge_path 完整包路径 */ public native static void patch(String path_pattern,int count,String merge_path); static { System.loadLibrary("mylibrary"); }}
2.javah生成的头文件
怎样生成头文件请参考超级简单的Android Studio jni 实现(无需命令行)
注意:新版Android Studio ndk-build 要指定Application.mk和Android.mk路径
/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class com_haocai_ndktest_NDKFileUtils */#ifndef _Included_com_haocai_ndktest_NDKFileUtils#define _Included_com_haocai_ndktest_NDKFileUtils#ifdef __cplusplusextern "C" {#endif/* * Class: com_haocai_ndktest_NDKFileUtils * Method: diff * Signature: (Ljava/lang/String;I)V */JNIEXPORT void JNICALL Java_com_haocai_ndktest_NDKFileUtils_diff (JNIEnv *, jclass, jstring ,jstring, jint);/* * Class: com_haocai_ndktest_NDKFileUtils * Method: patch * Signature: (Ljava/lang/String;I)V */JNIEXPORT void JNICALL Java_com_haocai_ndktest_NDKFileUtils_patch (JNIEnv *, jclass, jstring, jint, jstring);#ifdef __cplusplus}#endif#endif
3.根据生成的头文件写C程序
#include "com_haocai_ndktest_NDKFileUtils.h"#include #include #include #include #define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"kpioneer",FORMAT,__VA_ARGS__)#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"kpioneer",FORMAT,__VA_ARGS__)//获取文件大小long get_file_size( char *path){ FILE *fp = fopen(path,"rb"); fseek(fp,0,SEEK_END); return ftell(fp);}JNIEXPORT void JNICALL Java_com_haocai_ndktest_NDKFileUtils_diff(JNIEnv * env, jclass jcls, jstring path_jstr, jstring path_pattern_jstr, jint file_num) { //jstring -> char* //需要分割的文件路径 const char* path = (*env)->GetStringUTFChars(env, path_jstr, NULL); const char* path_pattern = (*env)->GetStringUTFChars(env, path_pattern_jstr, NULL); //得到分割之后的子文件路径列表 char **patches = malloc(sizeof(char*) * file_num); int i = 0; for (i = 0; i < file_num; i++) { patches[i] = malloc(sizeof(char) * 100); //元素复制 //需要分割的文件:C://jason/ sprintf(patches[i], path_pattern, (i + 1)); LOGI("patch path:%s", patches[i]); } //不断读取path文件,循环写入file_num的文件 //分割文件大小 //整除 //文件大小:90,分成9个文件,每个文件10 //不整除 //文件大小:110,分成9个文件 //前(9-1)个文件为(110/(9-1))=13 //最后一个文件(110%(9-1))=6 long filesize = get_file_size((char*)path); FILE *fpr = fopen(path, "rb"); //整除 if (filesize % file_num == 0) { //单个文件大小 int part = filesize / file_num; i = 0; //逐一写入不同的分割子文件 for (; i < file_num; i++) { FILE *fpw = fopen(patches[i], "wb"); int j = 0; for (; j < part; j++) { //边读边写 fputc(fgetc(fpr), fpw); } fclose(fpw); } } else { //不整除 int part = filesize / (file_num - 1); i = 0; //逐一写入不同的分割子文件 for (; i < file_num - 1; i++) { FILE *fpw = fopen(patches[i], "wb"); int j = 0; for (; j < part; j++) { //边读边写 fputc(fgetc(fpr), fpw); } fclose(fpw); } //the last one FILE *fpw = fopen(patches[file_num - 1], "wb"); i = 0; for (; i < filesize % (file_num - 1); i++) { fputc(fgetc(fpr), fpw); } fclose(fpw); } //关闭被分割的文件 fclose(fpr); //释放 i = 0; for (; i < file_num; i++) { free(patches[i]); } free(patches); (*env)->ReleaseStringUTFChars(env, path_jstr, path); (*env)->ReleaseStringUTFChars(env, path_pattern_jstr, path_pattern);}JNIEXPORT void JNICALL Java_com_haocai_ndktest_NDKFileUtils_patch(JNIEnv * env, jclass jcls, jstring path_pattern_jstr, jint file_num, jstring merge_path_jstr) { //合并之后的文件 const char* merge_path = (*env)->GetStringUTFChars(env, merge_path_jstr, NULL); //子文件 const char* path_pattern = (*env)->GetStringUTFChars(env, path_pattern_jstr, NULL); //得到分割之后的子文件路径列表 char **patches = malloc(sizeof(char*) * file_num); int i = 0; for (i = 0; i < file_num; i++) { patches[i] = malloc(sizeof(char) * 100); //元素复制 //需要分割的文件:C://jason/ sprintf(patches[i], path_pattern, (i + 1)); LOGI("patch path:%s", patches[i]); } FILE *fpw = fopen(merge_path, "wb"); //把所有的分割文件读取一遍,写入一个总的文件中 i = 0; for (; i < file_num; i++) { //每个字文件的大小 long filesize = get_file_size(patches[i]); FILE *fpr = fopen(patches[i], "rb"); int j = 0; for (; j < filesize; j++) { fputc(fgetc(fpr), fpw); } fclose(fpr); } fclose(fpw); //释放资源 (*env)->ReleaseStringUTFChars(env, path_pattern_jstr, path_pattern); (*env)->ReleaseStringUTFChars(env, merge_path_jstr, merge_path);}
4.写mk文件
Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := mylibraryLOCAL_SRC_FILES =: mylibrary.cLOCAL_LDLIBS := -lloginclude $(BUILD_SHARED_LIBRARY)
Applicatoin.mk
APP_MODULES := mylibraryAPP_ABI := armeabi-v7a armeabi arm64-v8a #定义编译目标版本 ABI(应用二进制接口) 值为all时,代表所有版本APP_PLATFORM := android-14
5.写Android调用库主程序
package com.haocai.ndktest;import android.os.Bundle;import android.os.Environment;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import java.io.File;public class MainActivity extends AppCompatActivity { private String SD_CARD_PATH; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SD_CARD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath(); } /** * 拆分包 * * @param v */ public void diffPackage(View v) { String path = SD_CARD_PATH + File.separator+ "小苹果.mp3"; String path_pattern = SD_CARD_PATH + File.separator +"小苹果_%d.mp3"; NDKFileUtils.diff(path, path_pattern,3); Log.d("Main","拆分成功"); } /** * 合并包 * * @param v */ public void patchPackage(View v) { String merge_path = SD_CARD_PATH + File.separator+ "小苹果_合并.mp3"; String path_pattern = SD_CARD_PATH + File.separator +"小苹果_%d.mp3"; NDKFileUtils.patch(path_pattern, 3,merge_path); Log.d("Main","合并成功"); }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
权限声明
6.运行结果
1.要把小苹果.mp3文件放在Android手机sd目录下
2.运行拆分包程序
生成 小苹果_1.mp3 小苹果_2.mp3 小苹果_3.mp3
3.运行合并包程序
生成 小苹果_合并.mp3
如下:
11-13 15:17:01.076 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_1.mp311-13 15:17:01.076 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_2.mp311-13 15:17:01.076 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_3.mp311-13 15:17:02.016 2648-2648/com.haocai.ndktest D/Main: 拆分成功11-13 15:17:02.026 2648-2648/com.haocai.ndktest I/Choreographer: Skipped 56 frames! The application may be doing too much work on its main thread.11-13 15:17:03.226 2648-2648/com.haocai.ndktest D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN11-13 15:17:03.286 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_1.mp311-13 15:17:03.286 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_2.mp311-13 15:17:03.286 2648-2648/com.haocai.ndktest I/kpioneer: patch path:/storage/emulated/0/小苹果_3.mp311-13 15:17:04.256 2648-2648/com.haocai.ndktest D/Main: 合并成功
先拆分后合并 该项目源码下载
特别感谢:
动脑学院Jason
更多相关文章
- android开发中build.gradle文件详解
- Android 获取assets的绝对路径
- Android在配置文件中配置Button再不同情况下的的背景
- Android通过SOCKET下载文件的方法
- 00_JNI头文件
- Android 之 使用Pull 解析xml文件
- android关于蓝牙不能传送APK文件
- Android布局文件-错误