# Android自助餐之Jni(四)在线导入so文件
- [Android自助餐之Jni四在线导入so文件](#)
- [上传so文件到服务器](#)
- [创建jni对应类](#)
- [在应用创建时加载so文件](#)
- [需要时进行调用](#)
下载[完整源代码](http://download.csdn.net/detail/xmh19936688/9395117)
### 上传so文件到服务器
此处已上传so文件到github。假设URL为:`https://raw.githubusercontent.com/***/libJniLibDemo.so`
### 创建jni对应类
本实例已知c文件内容如下
本实例已知c文件内容如下
~~~
JNIEXPORT jstring JNICALL
Java_com_xmh_jni_JniUtil_getResult(JNIEnv *env,jobject obj,jstring value){
char * str;
str=(*env)->GetStringUTFChars(env,value,NULL);
sprintf(str,"%s-_-%s",str,str);
return (*env)->NewStringUTF(env, str);
}
~~~
因此所创建的类完整类名为:com.xmh.jni.JniUtil。文件内容如下
~~~
public class JniUtil {
/**so文件的URL*/
private static String LIB_FILE_NET_PATH="https://raw.githubusercontent.com/***/libJniLibDemo.so";
//region so文件加载状态
/**未加载*/
public static int LIBRARY_LOAD_STATUS_NONE=0;
/**正在加载*/
public static int LIBRARY_LOAD_STATUS_LOADING=1;
/**已加载*/
public static int LIBRARY_LOAD_STATUS_LOADED=2;
/**so文件加载状态*/
private int libraryLoadStatus=LIBRARY_LOAD_STATUS_NONE;
//endregion
/**so文件加载回调*/
private DownloadStatusListener downloadStatusListener=null;
//region 单例模式
private static JniUtil jniUtil=null;
private JniUtil(){}
public static JniUtil getInstance(){
if(jniUtil!=null)return jniUtil;
return jniUtil=new JniUtil();
}
//endregion
/**获取so文件加载状态*/
public int getLibraryStatus(){
return libraryLoadStatus;
}
/**本地方法私有化,防止未加载就调用*/
public native String getResult(String value);
/**封装后的本地方法*/
public String getResult(Context context,String value){
//先判断是否加载了so文件
if(libraryLoadStatus==LIBRARY_LOAD_STATUS_NONE) {
loadLibrary(context);
return null;
}
return getResult(value);
}
/**加载so文件*/
public void loadLibrary(Context context) {
//设置加载状态
libraryLoadStatus=LIBRARY_LOAD_STATUS_LOADING;
try {
File libsDir = context.getDir("libs", Context.MODE_PRIVATE);
final String soFilePath=libsDir.getAbsolutePath() + "/libJniLibDemo.so";
Uri uri=Uri.parse(LIB_FILE_NET_PATH);
final DownloadRequest downloadRequest = new DownloadRequest(uri);
downloadRequest.setRetryPolicy(new DefaultRetryPolicy());//默认重试逻辑
downloadRequest.setDestinationURI(Uri.parse(soFilePath));
downloadRequest.setDownloadListener(new DownloadStatusListener() {
@Override
public void onDownloadComplete(int id) {
System.load(soFilePath);
libraryLoadStatus=LIBRARY_LOAD_STATUS_LOADED;//设置加载状态
if(downloadStatusListener!=null) downloadStatusListener.onDownloadComplete(id);
}
@Override
public void onDownloadFailed(int id, int errorCode, String errorMessage) {
libraryLoadStatus=LIBRARY_LOAD_STATUS_NONE;//设置加载状态
if(downloadStatusListener!=null) downloadStatusListener.onDownloadFailed(id, errorCode, errorMessage);
}
@Override
public void onProgress(int id, long totalBytes, long downloadedBytes, int progress) {
if(downloadStatusListener!=null) downloadStatusListener.onProgress(id,totalBytes,downloadedBytes,progress);
}
});
new ThinDownloadManager().add(downloadRequest);
} catch (Exception e) {
//设置加载状态
libraryLoadStatus=LIBRARY_LOAD_STATUS_NONE;
e.printStackTrace();
}
}
/**设置so文件加载回调*/
public void setOnDownloadListener(DownloadStatusListener listener){
this.downloadStatusListener =listener;
}
}
~~~
### 在应用创建时加载so文件
重写Application类如下
~~~
public class JniApplication extends Application{
/**在应用创建时开始加载so文件*/
@Override
public void onCreate() {
super.onCreate();
Log.e("xmh-jni", "app-create");
JniUtil.getInstance().loadLibrary(this);
}
}
~~~
### 需要时进行调用
~~~
final JniUtil jniUtil = JniUtil.getInstance();
//判断是否已加载so文件,如已加载则调用封装后的本地方法,否则设置加载回调后开始加载so文件
if(jniUtil.getLibraryStatus()==JniUtil.LIBRARY_LOAD_STATUS_LOADED) {
tvResult.setText(jniUtil.getResult(this, "xmh"));
}else {
jniUtil.setOnDownloadListener(new DownloadStatusListener() {
@Override
public void onDownloadComplete(int id) {
//加载完成后执行操作
tvResult.setText(jniUtil.getResult(MainActivity.this, "xmh"));
}
@Override
public void onDownloadFailed(int id, int errorCode, String errorMessage) {
}
@Override
public void onProgress(int id, long totalBytes, long downloadedBytes, int progress) {
}
});
jniUtil.loadLibrary(this);
}
~~~