# 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);
}
~~~