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路径

Android NDK开发之旅16--NDK--文件拆分与合并_第1张图片

/* 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: 合并成功
Android NDK开发之旅16--NDK--文件拆分与合并_第2张图片 先拆分后合并
该项目源码下载

特别感谢:
动脑学院Jason







Android NDK开发之旅16--NDK--文件拆分与合并_第3张图片 微信号kpioneer

更多相关文章

  1. android开发中build.gradle文件详解
  2. Android 获取assets的绝对路径
  3. Android在配置文件中配置Button再不同情况下的的背景
  4. Android通过SOCKET下载文件的方法
  5. 00_JNI头文件
  6. Android 之 使用Pull 解析xml文件
  7. android关于蓝牙不能传送APK文件
  8. Android布局文件-错误

随机推荐

  1. 浅谈mysql 系统用户最大文件打开数限制
  2. 分组查询GROUP BY的使用与SQL执行顺序的
  3. 数据库SQL SELECT查询的工作原理
  4. MySQL可重复读级别能够解决幻读吗
  5. MySQL优化方案参考
  6. MySQL不同表之前的字段复制
  7. MySQL索引类型Normal、Unique和Full Text
  8. MySQL分库分表总结讲解
  9. MySQL数据库存储过程和事务的区别讲解
  10. MySQL Limit性能优化及分页数据性能优化