RN集成自签名https及双向认证-android(2)
上一篇文章讲了ios的这里接着讲RN-android-自签名https的配置,首先android比较复杂,首先用AS打开android工程
android有4个地方得改
- fetch (.jar包里的代码不能直接改)
- webview (.jar包里的代码不能直接改)
- Image (.jar包里的代码不能直接改--)
- react-native-fetch-blob(可以直接改源码-RNFetchBlobReq
RNFetchBlob 这两个类) - 如果使用了react-native-navigation时,在我们copy出MainReactPackage使用时会报错,注释掉react-native-navigation报错的地方就行
注意:RN的不同版本,会有不同的依赖问题,得根据报错一个一个改,很麻烦
fetch
-
修改路径和原理
安卓三方的依赖库在这可以看到
AADFC784-0EDE-4B65-8633-7577568F4294.png
NetworkingModule.java文件就是我们android最底层的网络请求工具类,每次创建NetworkingModule对象的时候,我们会传入一个okhttpclient的对象:
public NetworkingModule(ReactApplicationContext context) { this(context, (String)null, OkHttpClientProvider.createClient(), (List)null); } public NetworkingModule(ReactApplicationContext context, List networkInterceptorCreators) { this(context, (String)null, OkHttpClientProvider.createClient(), networkInterceptorCreators); } public NetworkingModule(ReactApplicationContext context, String defaultUserAgent) { this(context, defaultUserAgent, OkHttpClientProvider.createClient(), (List)null); }
可以看到,每次都是通过:
OkHttpClientProvider.createClient()
的方式创建了一个okhttpclient对象,最后发送请求为:
@ReactMethod public void sendRequest(ExecutorToken executorToken, String method, String url, final int requestId, ReadableArray headers, ReadableMap data, final String responseType, final boolean useIncrementalUpdates, int timeout) { okhttp3.Request.Builder requestBuilder = (new okhttp3.Request.Builder()).url(url); if(requestId != 0) { requestBuilder.tag(Integer.valueOf(requestId)); } final RCTDeviceEventEmitter eventEmitter = this.getEventEmitter(executorToken); Builder clientBuilder = this.mClient.newBuilder(); ....
所以我们只需要替换掉默认的httpclient,然后为其添加上证书认证就可以了,我们打开 OkHttpClientProvider.createClient()方法:
public static OkHttpClient createClient() { Builder client = (new Builder()).connectTimeout(0L, TimeUnit.MILLISECONDS).readTimeout(0L, TimeUnit.MILLISECONDS).writeTimeout(0L, TimeUnit.MILLISECONDS).cookieJar(new ReactCookieJarContainer()); return enableTls12OnPreLollipop(client).build(); }
OkHttpClientProvider这个工具类就是为我们提供了一个修改默认okhttpclient的方法,我们看到其中有一个方法:
public static void replaceOkHttpClient(OkHttpClient client) { sClient = client; }
这个方法就是替换掉rn中网络请求默认的okhttpclient方法。
所以我们在程序初始化的时候改掉默认的okhttpclient.
- 首先找到你项目的application文件,在oncreate方法中提供其方法:
@Override public void onCreate() { ... //RN OKHTTP添加https证书 OkHttpClientProvider.replaceOkHttpClient(initCustomOkHttpClient()); ... }//自定义初始化client方法-public OkHttpClient initCustomOkHttpClient() { OkHttpClient.Builder client = new OkHttpClient.Builder() .connectTimeout(30 * 1000, TimeUnit.MILLISECONDS) .readTimeout(30 * 1000, TimeUnit.MILLISECONDS) .writeTimeout(30 * 1000, TimeUnit.MILLISECONDS) .cookieJar(new ReactCookieJarContainer()); client.addNetworkInterceptor(new StethoInterceptor()); client.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)); try { //你的证书文件,放在android的assets文件夹下 setCertificates(client, getAssets().open("CA.crt")); client.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); } catch (IOException e) { e.printStackTrace(); } OkHttpClient.Builder builder = OkHttpClientProvider.enableTls12OnPreLollipop(client); return builder.build(); }//处理证书public void setCertificates(OkHttpClient.Builder client, InputStream... certificates) { try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; for (InputStream certificate : certificates) { String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); try { if (certificate != null) certificate.close(); } catch (IOException e) { } } SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); sslContext.init( null, trustManagerFactory.getTrustManagers(), new SecureRandom() ); client.sslSocketFactory(sslContext.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } }
- 修改NetworkingModule.java文件的以下方法,把默认创建okhttpclient的方式:OkHttpClientProvider.createClient(),全部改为:OkHttpClientProvider.getOkHttpClient()
public NetworkingModule(ReactApplicationContext context) { this(context, (String)null, OkHttpClientProvider.createClient(), (List)null); } public NetworkingModule(ReactApplicationContext context, List networkInterceptorCreators) { this(context, (String)null, OkHttpClientProvider.createClient(), networkInterceptorCreators); } public NetworkingModule(ReactApplicationContext context, String defaultUserAgent) { this(context, defaultUserAgent, OkHttpClientProvider.createClient(), (List)null); }
如下:
/** * @param context the ReactContext of the application */ public NetworkingModule(final ReactApplicationContext context) { this(context, null, OkHttpClientProvider.getOkHttpClient(), null); } /** * @param context the ReactContext of the application * @param networkInterceptorCreators list of {@link NetworkInterceptorCreator}'s whose create() * methods would be called to attach the interceptors to the client. */ public NetworkingModule( ReactApplicationContext context, List networkInterceptorCreators) { this(context, null, OkHttpClientProvider.getOkHttpClient(), networkInterceptorCreators); } /** * @param context the ReactContext of the application * @param defaultUserAgent the User-Agent header that will be set for all requests where the * caller does not provide one explicitly */ public NetworkingModule(ReactApplicationContext context, String defaultUserAgent) { this(context, defaultUserAgent, OkHttpClientProvider.getOkHttpClient(), null); }
问题:react-native的第三方依赖库,改不了源码咋办呢?
我们直接copy一份NetworkingModule跟mainreactpackage的代码,然后在application中把mainreactpackage替换成我们copy出去的那一份,
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( //替换成我们copy的那个文件 new MainReactPackage(), new VectorIconsPackage(), new RCTSplashScreenPackage(), new RNDeviceInfo(), new AndroidModulePackage(), new RCTSwipeRefreshLayoutPackage() ); } };
然后点进我们copy的那个MainReactPackage文件,再把MainReactPackage中的:
new ModuleSpec(NetworkingModule.class, new Provider() { @Override public NativeModule get() { //替换成我们自己copy的那个文件 return new NetworkingModule(context); } }),
MainReactPackage路径.png -
Image部分
android_Image路径.png
但是RN对应的那一部分.jar包是不可改的,,主要的问题还是怎么去改动代码
摘要 :
如何改动android.jar 包rn_androi_https
MainReactPackage路径.png
- webView
- ReactWebviewManager.java
/*** Copyright (c) 2015-present, Facebook, Inc.* All rights reserved.* * This source code is licensed under the BSD-style license found in the* LICENSE file in the root directory of this source tree. An additional grant* of patent rights can be found in the PATENTS file in the same directory.*/package petrochina.cplh.qqgl2.htttps;import android.content.ActivityNotFoundException;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.Picture;import android.net.Uri;import android.os.Build;import android.text.TextUtils;import android.util.Log;import android.view.ViewGroup.LayoutParams;import android.webkit.ConsoleMessage;import android.webkit.CookieManager;import android.webkit.GeolocationPermissions;import android.webkit.JavascriptInterface;import android.webkit.ValueCallback;import android.webkit.WebChromeClient;import android.webkit.WebResourceResponse;import android.webkit.WebSettings;import android.webkit.WebView;import android.webkit.WebViewClient;import com.facebook.common.logging.FLog;import com.facebook.react.bridge.Arguments;import com.facebook.react.bridge.LifecycleEventListener;import com.facebook.react.bridge.ReactContext;import com.facebook.react.bridge.ReadableArray;import com.facebook.react.bridge.ReadableMap;import com.facebook.react.bridge.ReadableMapKeySetIterator;import com.facebook.react.bridge.WritableMap;import com.facebook.react.common.MapBuilder;import com.facebook.react.common.ReactConstants;import com.facebook.react.common.build.ReactBuildConfig;import com.facebook.react.module.annotations.ReactModule;import com.facebook.react.uimanager.SimpleViewManager;import com.facebook.react.uimanager.ThemedReactContext;import com.facebook.react.uimanager.UIManagerModule;import com.facebook.react.uimanager.annotations.ReactProp;import com.facebook.react.uimanager.events.ContentSizeChangeEvent;import com.facebook.react.uimanager.events.Event;import com.facebook.react.uimanager.events.EventDispatcher;import com.facebook.react.views.webview.WebViewConfig;import com.facebook.react.views.webview.events.TopLoadingErrorEvent;import com.facebook.react.views.webview.events.TopLoadingFinishEvent;import com.facebook.react.views.webview.events.TopLoadingStartEvent;import com.facebook.react.views.webview.events.TopMessageEvent;import org.json.JSONException;import org.json.JSONObject;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.UnsupportedEncodingException;import java.net.URL;import java.security.KeyStore;import java.security.cert.CertificateFactory;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Locale;import java.util.Map;import javax.annotation.Nullable;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.TrustManagerFactory;/*** Manages instances of {@link WebView}*
* Can accept following commands:* - GO_BACK* - GO_FORWARD* - RELOAD*
* {@link WebView} instances could emit following direct events:* - topLoadingFinish* - topLoadingStart* - topLoadingError*
* Each event will carry the following properties:* - target - view's react tag* - url - url set for the webview* - loading - whether webview is in a loading state* - title - title of the current page* - canGoBack - boolean, whether there is anything on a history stack to go back* - canGoForward - boolean, whether it is possible to request GO_FORWARD command*/@ReactModule(name = ReactWebViewManager.REACT_CLASS)public class ReactWebViewManager extends SimpleViewManager { protected static final String REACT_CLASS = "RCTWebView"; protected static final String HTML_ENCODING = "UTF-8"; protected static final String HTML_MIME_TYPE = "text/html"; protected static final String BRIDGE_NAME = "__REACT_WEB_VIEW_BRIDGE"; protected static final String HTTP_METHOD_POST = "POST"; public static final int COMMAND_GO_BACK = 1; public static final int COMMAND_GO_FORWARD = 2; public static final int COMMAND_RELOAD = 3; public static final int COMMAND_STOP_LOADING = 4; public static final int COMMAND_POST_MESSAGE = 5; public static final int COMMAND_INJECT_JAVASCRIPT = 6; // Use `webView.loadUrl("about:blank")` to reliably reset the view // state and release page resources (including any running JavaScript). protected static final String BLANK_URL = "about:blank"; protected WebViewConfig mWebViewConfig; protected @Nullable WebView.PictureListener mPictureListener; private static ThemedReactContext reactContext; protected static class ReactWebViewClient extends WebViewClient { // ---https 双向认证------ private SSLContext sslContext; public ReactWebViewClient() { // 添加https证书 try { InputStream is = reactContext.getAssets().open("CNPCCA.cer"); NetConfig.addCertificate(is); // 这里将证书读取出来,,放在配置中byte[]里 } catch (IOException ioe) { ioe.printStackTrace(); } // 添加证书cer List certificates = new ArrayList<>(); List certs_data = NetConfig.getCertificatesData(); // 将字节数组转为数组输入流 if (certs_data != null && !certs_data.isEmpty()) { for (byte[] bytes : certs_data) { certificates.add(new ByteArrayInputStream(bytes)); } } try { prepareSslPinning(certificates); } catch (IOException e) { e.printStackTrace(); } } @Override public WebResourceResponse shouldInterceptRequest(final WebView view, String url) { Log.i("shouldInterceptRequest", "shouldInterceptRequest1"); if (url.indexOf("https") != -1) { return processRequest(url); } else { return null; } } private WebResourceResponse processRequest(String webUrl) {// LogUtils.i("SSL_PINNING_WEBVIEWS", "GET: " + webUrl.toString()); try { // Setup connection URL url = new URL(webUrl); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); // Set SSL Socket Factory for this request urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); urlConnection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } });//很重要,校验证书 // Get content, contentType and encoding InputStream is = urlConnection.getInputStream(); String contentType = urlConnection.getContentType(); String encoding = urlConnection.getContentEncoding(); // If got a contentType header if (contentType != null) { String mimeType = contentType; // Parse mime type from contenttype string if (contentType.contains(";")) { mimeType = contentType.split(";")[0].trim(); }// LogUtils.i("SSL_PINNING_WEBVIEWS", "Mime: " + mimeType); // Return the response return new WebResourceResponse(mimeType, encoding, is); } } catch (Exception e) { e.printStackTrace();// LogUtils.i("SSL_PINNING_WEBVIEWS", e.getLocalizedMessage()); } // Return empty response for this request return new WebResourceResponse(null, null, null); } private void prepareSslPinning(List certificates) throws IOException { try { // 服务器端需要验证的客户端证书,其实就是客户端的keystore KeyManagerFactory keyManagerFactory = KeyManagerFactory .getInstance("X509"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); KeyStore keyStore = KeyStore.getInstance("PKCS12"); KeyStore keyStore2 = KeyStore.getInstance(KeyStore.getDefaultType()); //读取证书 InputStream ksIn = reactContext.getResources().getAssets().open("client.p12");//***:你的p12证书 //加载证书 keyStore2.load(null); keyStore.load(ksIn, "cplh123456".toCharArray());//***:p12证书的密码,必须 ksIn.close(); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); try { for (int i = 0, size = certificates.size(); i < size; ) { InputStream certificate = certificates.get(i); String certificateAlias = Integer.toString(i++); keyStore2.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); if (certificate != null) certificate.close(); } } catch (IOException e) { e.printStackTrace(); } sslContext = SSLContext.getInstance("TLS");// TrustManagerFactory trustManagerFactory =//// TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, "cplh123456".toCharArray()); trustManagerFactory.init(keyStore2); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); } catch (Exception e) { e.printStackTrace(); } } // ---https 双向认证------ protected boolean mLastLoadFailed = false; protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent; @Override public void onPageFinished(WebView webView, String url) { super.onPageFinished(webView, url); if (!mLastLoadFailed) { ReactWebView reactWebView = (ReactWebView) webView; reactWebView.callInjectedJavaScript(); reactWebView.linkBridge(); emitFinishEvent(webView, url); } } @Override public void onPageStarted(WebView webView, String url, Bitmap favicon) { super.onPageStarted(webView, url, favicon); mLastLoadFailed = false; dispatchEvent( webView, new TopLoadingStartEvent( webView.getId(), createWebViewEvent(webView, url))); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { boolean useDefaultIntent = false; if (mUrlPrefixesForDefaultIntent != null && mUrlPrefixesForDefaultIntent.size() > 0) { ArrayList
- react-native-fetch-blob
-
RNFetchBlobReq
RNFetchBlobReq.png -
RNFetchBlob
RNFetchBlob.png
-
package com.RNFetchBlob;import android.app.Activity;import android.app.DownloadManager;import android.content.Intent;import android.net.Uri;import com.facebook.react.bridge.ActivityEventListener;import com.facebook.react.bridge.Callback;import com.facebook.react.bridge.LifecycleEventListener;import com.facebook.react.bridge.Promise;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import com.facebook.react.bridge.ReadableArray;import com.facebook.react.bridge.ReadableMap;// Cookiesimport com.facebook.react.bridge.WritableMap;import com.facebook.react.modules.network.ForwardingCookieHandler;import com.facebook.react.modules.network.CookieJarContainer;import com.facebook.react.modules.network.OkHttpClientProvider;import com.facebook.react.modules.network.ReactCookieJarContainer;import okhttp3.OkHttpClient;import okhttp3.JavaNetCookieJar;import java.io.IOException;import java.io.InputStream;import java.security.KeyStore;import java.security.SecureRandom;import java.security.cert.CertificateFactory;import java.util.HashMap;import java.util.Map;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.TrustManagerFactory;import static android.app.Activity.RESULT_OK;import static com.RNFetchBlob.RNFetchBlobConst.GET_CONTENT_INTENT;public class RNFetchBlob extends ReactContextBaseJavaModule { // Cookies private final ForwardingCookieHandler mCookieHandler; private final CookieJarContainer mCookieJarContainer; private final OkHttpClient mClient; static ReactApplicationContext RCTContext; static LinkedBlockingQueue taskQueue = new LinkedBlockingQueue<>(); static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5000, TimeUnit.MILLISECONDS, taskQueue); static LinkedBlockingQueue fsTaskQueue = new LinkedBlockingQueue<>(); static ThreadPoolExecutor fsThreadPool = new ThreadPoolExecutor(2, 10, 5000, TimeUnit.MILLISECONDS, taskQueue); static public boolean ActionViewVisible = false; static HashMap promiseTable = new HashMap<>(); //https --修改 -- public OkHttpClient initCustomOkHttpClient() { OkHttpClient.Builder client = new OkHttpClient.Builder() .connectTimeout(30 * 1000, TimeUnit.MILLISECONDS) .readTimeout(30 * 1000, TimeUnit.MILLISECONDS) .writeTimeout(30 * 1000, TimeUnit.MILLISECONDS) .cookieJar(new ReactCookieJarContainer());// client.addNetworkInterceptor(new StethoInterceptor());// client.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)); try { //你的证书文件,放在android的assets文件夹下 setCertificates(client, RCTContext.getAssets().open("CNPCCA.cer")); client.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); } catch (IOException e) { e.printStackTrace(); } OkHttpClient.Builder builder = OkHttpClientProvider.enableTls12OnPreLollipop(client); return builder.build(); } public void setCertificates(OkHttpClient.Builder client, InputStream... certificates) { try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; for (InputStream certificate : certificates) { String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); try { if (certificate != null) certificate.close(); } catch (IOException e) { } } SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); //初始化keystore KeyStore clientKeyStore = KeyStore.getInstance("BKS"); clientKeyStore.load(RCTContext.getAssets().open("client.bks"), "mima".toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, "mima".toCharArray()); sslContext.init( keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom() ); client.sslSocketFactory(sslContext.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } //https --修改 -- public RNFetchBlob(ReactApplicationContext reactContext) { super(reactContext); RCTContext = reactContext; mClient = initCustomOkHttpClient(); mCookieHandler = new ForwardingCookieHandler(reactContext); mCookieJarContainer = (CookieJarContainer) mClient.cookieJar(); mCookieJarContainer.setCookieJar(new JavaNetCookieJar(mCookieHandler)); reactContext.addActivityEventListener(new ActivityEventListener() { @Override public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { if(requestCode == GET_CONTENT_INTENT && resultCode == RESULT_OK) { Uri d = data.getData(); promiseTable.get(GET_CONTENT_INTENT).resolve(d.toString()); promiseTable.remove(GET_CONTENT_INTENT); } } @Override public void onNewIntent(Intent intent) { } }); } @Override public String getName() { return "RNFetchBlob"; } @Override public Map getConstants() { return RNFetchBlobFS.getSystemfolders(this.getReactApplicationContext()); } @ReactMethod public void createFile(final String path, final String content, final String encode, final Callback callback) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.createFile(path, content, encode, callback); } }); } @ReactMethod public void actionViewIntent(String path, String mime, final Promise promise) { try { Intent intent= new Intent(Intent.ACTION_VIEW) .setDataAndType(Uri.parse("file://" + path), mime); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.getReactApplicationContext().startActivity(intent); ActionViewVisible = true; final LifecycleEventListener listener = new LifecycleEventListener() { @Override public void onHostResume() { if(ActionViewVisible) promise.resolve(null); RCTContext.removeLifecycleEventListener(this); } @Override public void onHostPause() { } @Override public void onHostDestroy() { } }; RCTContext.addLifecycleEventListener(listener); } catch(Exception ex) { promise.reject(ex.getLocalizedMessage()); } } @ReactMethod public void createFileASCII(final String path, final ReadableArray dataArray, final Callback callback) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.createFileASCII(path, dataArray, callback); } }); } @ReactMethod public void writeArrayChunk(final String streamId, final ReadableArray dataArray, final Callback callback) { RNFetchBlobFS.writeArrayChunk(streamId, dataArray, callback); } @ReactMethod public void unlink(String path, Callback callback) { RNFetchBlobFS.unlink(path, callback); } @ReactMethod public void mkdir(String path, Callback callback) { RNFetchBlobFS.mkdir(path, callback); } @ReactMethod public void exists(String path, Callback callback) { RNFetchBlobFS.exists(path, callback); } @ReactMethod public void cp(final String path, final String dest, final Callback callback) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.cp(path, dest, callback); } }); } @ReactMethod public void mv(String path, String dest, Callback callback) { RNFetchBlobFS.mv(path, dest, callback); } @ReactMethod public void ls(String path, Callback callback) { RNFetchBlobFS.ls(path, callback); } @ReactMethod public void writeStream(String path, String encode, boolean append, Callback callback) { new RNFetchBlobFS(this.getReactApplicationContext()).writeStream(path, encode, append, callback); } @ReactMethod public void writeChunk(String streamId, String data, Callback callback) { RNFetchBlobFS.writeChunk(streamId, data, callback); } @ReactMethod public void closeStream(String streamId, Callback callback) { RNFetchBlobFS.closeStream(streamId, callback); } @ReactMethod public void removeSession(ReadableArray paths, Callback callback) { RNFetchBlobFS.removeSession(paths, callback); } @ReactMethod public void readFile(final String path, final String encoding, final Promise promise) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.readFile(path, encoding, promise); } }); } @ReactMethod public void writeFileArray(final String path, final ReadableArray data, final boolean append, final Promise promise) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.writeFile(path, data, append, promise); } }); } @ReactMethod public void writeFile(final String path, final String encoding, final String data, final boolean append, final Promise promise) { threadPool.execute(new Runnable() { @Override public void run() { RNFetchBlobFS.writeFile(path, encoding, data, append, promise); } }); } @ReactMethod public void lstat(String path, Callback callback) { RNFetchBlobFS.lstat(path, callback); } @ReactMethod public void stat(String path, Callback callback) { RNFetchBlobFS.stat(path, callback); } @ReactMethod public void scanFile(final ReadableArray pairs, final Callback callback) { final ReactApplicationContext ctx = this.getReactApplicationContext(); threadPool.execute(new Runnable() { @Override public void run() { int size = pairs.size(); String [] p = new String[size]; String [] m = new String[size]; for(int i=0;i
原理就是,import我们copy改动的类,不再使用.jar包里的类,option+return自动import包路径
具体查看管知汇,前期管理
更多相关文章
- Android源码获取方法
- Handler
- Android进程系列第六篇---LowmemoryKiller机制分析(上)
- Android(安卓)基础
- adb shell 命令详解
- 浅谈Java中Collections.sort对List排序的两种方法
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程