标签:重复 ret 菜单 oid 文件 define 编译 lis tle
增量更新大量用于 Android各大应用市场.本文想做网络上从服务器到app客户端完整讲解.app用eclipse和android studio 最新版cmark开发ndk
如下图:
以前一直好奇怎么做的直到知道了bsdiff库.
地址附上:
bsdiff源码地址和简介
假设你用的是”XXX市场”点击更新的时候,把当前版本号和服务器最新版app版本号对比用bsdiff生成差异包,然后将差异包返回下载,下载后将本地应用app的apk文件和差异包用bspatch合成新的apk在安装.
bsdiff源码点击官网中”here”下载 :
懒人链接
bzip2源码下载:
bzip2官网链接
bzip2下载链接
下载后bsdiff源码文件如下:
我们服务器要生成差异文件,那么只需要bsdiff.c 即可.
我们先简单阅读下bsdiff源码(我们直接看启动方法main):
从上图可知 传入的参数args需要等于4 不然报错.各个参数已经在上图解释
由于main方法很特殊(启动方法,和java的main意义一样所以我们改一个方法名) 所以在这里我们改一个名字为 bsdiff_main
编写对应java的jni方法并生成头文件.(如果大家对jni不熟悉的,就按照本博客操作即可,尽量做到让大家都明白)
package com.fmy;
public class JAVABsdiff {
public static void main(String[] args) {
}
//jni方法 用于调用bsdiff
public static native void myBsdiff(String []args);
}
1. 打开命令窗口
2. 打开目录到java工程目录到src下
3. 输入javah 包名.类名 生成对应 "xxx.h"头文件
此时会在你java到src目录生成xx.h文件(请按F5刷新)
我们顺便打开这个文件看看
可以看到里面有一个c语言方法
JNIEXPORT void JNICALL Java_com_fmy_JAVABsdiff_myBsdiff
(JNIEnv *, jclass, jobjectArray);
我们待会创建一个c文件实现它并将它与bsdiff_main方法关联
#include "com_fmy_JAVABsdiff.h"
#include<stdio.h>
#include"bsdiff.h"
JNIEXPORT void JNICALL Java_com_fmy_JAVABsdiff_myBsdiff
(JNIEnv * env, jclass jclas,jobjectArray attas){
//GetObjectArrayElement得到到是jstring类型 而我们调用bsdiff_main()传入的
//是char× 数组 所以需要转化。这里需要jni知识 所以就不太多了,你只需把下面到内容
//复制到你到项目中即可
//旧文件地址
jstring a0 = (*env)->GetObjectArrayElement(env,attas,0);
//转化为char ×
char *j=(char*)(*env)->GetStringUTFChars(env,a0,NULL);
//
jstring a1 = (*env)->GetObjectArrayElement(env,attas,1);
char *j1=(char*)(*env)->GetStringUTFChars(env,a1,NULL);
jstring a2 = (*env)->GetObjectArrayElement(env,attas,2);
char *j2=(char*)(*env)->GetStringUTFChars(env,a2,NULL);
char * agrs[] = {"patch",j,j1,j2};
bsdiff_main(4,agrs);
}
打开命令窗口 打开此目录输入
$ gcc *.c -fPIC -shared -o libtest.so
然后报错
为什么报错?因为 前面用javah生成头文件中导入了jni.h 这里大家可以回头看看。第二我们使用env这个变量 也是jni里面所有我们需要导入。
问题来了jni.h在哪?
位于java安装目录include下
ok我们把这个文件复制到刚才编译目录下,继续编译
又报错发现缺少jni_md.h 文件
报错原因:因为jni.h内部引用了jni_md.h
jni_md.h在哪?
在java安装目录到include到linux下
我们在最后编译下
发现还是报错xxx.c中定义main重复定义了
大家这里可以看着报错到文件 去到文件直接把main方法删除了或注释
这里我就带大家注释其中到bzip2recover.c的main
删除或则注释上面高亮部分
其他文件大家自己删除把
再次编译一次 快疯了。。。。。
编译通过了!
此时在目录下会生成test.so
在java调用so
package com.fmy;
public class JAVABsdiff {
static{
System.load("/media/fmy/新加卷/增量/完整/test.so");
}
public static void main(String[] args) {
String oldfile = "/media/fmy/新加卷/增量/old.tar";
String newfile = "/media/fmy/新加卷/增量/new.tar";
String patch = "/media/fmy/新加卷/增量/patch.patch";
myBsdiff(new String[]{oldfile,newfile,patch});
System.out.println("asd");
}
//生成静态到patch文件
public static native void myBsdiff(String []args);
}
elipse 需要安装cdt插件
新建C project。
导入第一中编译方式 最后一步的所有文件到工程中
eclipse cdt编译参考文献1
eclipse cdt编译参考文献2
右键选择Android Tools—>>Add Native Support 点击确定
此时会在目录生成 生成一个lib目录 并且自动生成一个.cpp和Android.mk文件
创建jni方法
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static native void path(String []arrays);
}
生jni方法头文件放入jni中
把去掉bzip2源码中所有的main方法的文件拷贝到jni目录下,
创建一个test.c文件放入jni目录
把 bspatch.c放入jni目录.并修改对应的main
修改bspatch.c导入的bzip.h路径
我们顺带看jni 目录
编写test.c实现
#include "com_fmy_JAVA_bs.h"
#include<stdio.h>
JNIEXPORT void JNICALL Java_com_fmy_JAVA_1bs_myBsDiff
(JNIEnv * env, jclass jclas,jobjectArray attas){
jstring a0 = (*env)->GetObjectArrayElement(env,attas,0);
char *j=(*env)->GetStringUTFChars(env,a0,NULL);
jstring a1 = (*env)->GetObjectArrayElement(env,attas,1);
char *j1=(*env)->GetStringUTFChars(env,a1,NULL);
jstring a2 = (*env)->GetObjectArrayElement(env,attas,2);
char *j2=(*env)->GetStringUTFChars(env,a2,NULL);
char * agrs[] = {"patch",j,j1,j2};
bsdiff_main(4,agrs);
}
修改Android.mk文件如下
LOCAL_PATH := $(call my-dir)
#目的便利jni目录下所有的.c文件
MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.c)
#目的便利jni/bzip2目录下所有的.c文件
MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/bzip2/*.c)
include $(CLEAR_VARS)
LOCAL_MODULE := bspatch
LOCAL_SRC_FILES := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%)
#导入Android 日志 库可以在jni中使用Log.e方法等
LOCAL_LDLIBS:= -llog
include $(BUILD_SHARED_LIBRARY)
public class MainActivity extends Activity {
static{
System.loadLibrary("bspatch");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这里用zip包模拟 增量更新不止用于 apk哦亲
File oldFile = new File(Environment.getExternalStorageDirectory(),"old.zip");
File newFile = new File(Environment.getExternalStorageDirectory(),"new.zip");
File patchFile = new File(Environment.getExternalStorageDirectory(),"path.patch");
path(new String [] {oldFile.getAbsolutePath(),newFile.getAbsolutePath(),patchFile.getAbsolutePath()});
// path();
Log.e("test", "asd");
// Log.e("fmy", "============"+path);
}
// public static native void path();
public static native void path(String []arrays);
}
用CMake 构建ndk开发,这里不详细说了
CMake教程
用as创建一个工程的时候勾选 ‘include c++ support’
此时 工程目录下有个main/cpp文件夹
项目工程下会有个CMakeList.txt文件
创建一个jni方法
public class MainActivity extends AppCompatActivity {
// Used to load the ‘native-lib‘ library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* A native method that is implemented by the ‘native-lib‘ native library,
* which is packaged with this application.
*/
public static native void path(String []arrays);
}
tip:在新版的studio直接鼠标方法jni方法上直接按下Alt+回车键直接生产对应实现方法哦.
这里我们在cpp/native-lib.c实现
#include <jni.h>
#include "stdio.h"
#include "android/log.h"
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,__VA_ARGS__)
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,__VA_ARGS__)
#include "bzip2-1.0.6/bspatch.h"
JNIEXPORT void JNICALL
Java_com_myself_weather_testjni2_MainActivity_path(JNIEnv *env, jclass tjype, jobjectArray arrays) {
jstring a0 = (*env)->GetObjectArrayElement(env,arrays,0);
char *j=(*env)->GetStringUTFChars(env,a0,NULL);
jstring a1 = (*env)->GetObjectArrayElement(env,arrays,1);
char *j1=(*env)->GetStringUTFChars(env,a1,NULL);
jstring a2 = (*env)->GetObjectArrayElement(env,arrays,2);
char *j2=(*env)->GetStringUTFChars(env,a2,NULL);
char * agrs[] = {"patch",j,j1,j2};
mybspatch_main(4,agrs);
LOGE("FMY%s",j);
LOGE("FMY%s",j1);
LOGE("FMY%s",j2);
}
导入bspatch.c导入cpp目录下(记得修改main方法名字和eclipse一样)
修改CmarkList.txt文件
最后合成
package com.myself.weather.testjni2;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import java.io.File;
public class MainActivity extends AppCompatActivity {
// Used to load the ‘native-lib‘ library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File oldFile = new File(Environment.getExternalStorageDirectory(),"old.zip");
File newFile = new File(Environment.getExternalStorageDirectory(),"new.zip");
File patchFile = new File(Environment.getExternalStorageDirectory(),"path.patch");
path(new String [] {oldFile.getAbsolutePath(),newFile.getAbsolutePath(),patchFile.getAbsolutePath()});
}
});
}
/**
* A native method that is implemented by the ‘native-lib‘ native library,
* which is packaged with this application.
*/
public static native void path(String []arrays);
}
标签:重复 ret 菜单 oid 文件 define 编译 lis tle
原文地址:http://blog.csdn.net/qfanmingyiq/article/details/70215295