Performance (#626)
This commit is contained in:
parent
57691fcd99
commit
d266b9f55b
6 changed files with 390 additions and 85 deletions
2
app
2
app
|
@ -1 +1 @@
|
|||
Subproject commit 60b4210c530e82b6f6d47e0b4e41b35fe24a2617
|
||||
Subproject commit 836ff2ae134d3cd3b114b88a64a7cdd0900582c9
|
|
@ -74,8 +74,6 @@ public class LbrynetService extends PythonService {
|
|||
|
||||
public static LbrynetService serviceInstance;
|
||||
|
||||
private static final String SDK_URL = "http://127.0.0.1:5279";
|
||||
|
||||
private static final int SDK_POLL_INTERVAL = 500; // 500 milliseconds
|
||||
|
||||
private BroadcastReceiver stopServiceReceiver;
|
||||
|
@ -192,86 +190,10 @@ public class LbrynetService extends PythonService {
|
|||
}
|
||||
}
|
||||
|
||||
private String sdkCall(String method) throws ConnectException {
|
||||
return sdkCall(method, null);
|
||||
}
|
||||
|
||||
private String sdkCall(String method, Map<String, String> params) throws ConnectException {
|
||||
BufferedReader reader = null;
|
||||
DataOutputStream dos = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
try {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("method", method);
|
||||
if (params != null) {
|
||||
JSONObject requestParams = new JSONObject();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
requestParams.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
request.put("params", requestParams);
|
||||
}
|
||||
|
||||
URL url = new URL(SDK_URL);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-type", "application/json");
|
||||
|
||||
dos = new DataOutputStream(conn.getOutputStream());
|
||||
dos.writeBytes(request.toString());
|
||||
dos.flush();
|
||||
dos.close();
|
||||
|
||||
if (conn.getResponseCode() == 200) {
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String input;
|
||||
while ((input = reader.readLine()) != null) {
|
||||
sb.append(input);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
} else {
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String error;
|
||||
while ((error = reader.readLine()) != null) {
|
||||
sb.append(error);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
} catch (ConnectException ex) {
|
||||
// sdk not started yet. rethrow
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, ex.getMessage(), ex);
|
||||
// ignore and continue
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, ex.getMessage(), ex);
|
||||
// ignore
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void pollFileList() {
|
||||
try {
|
||||
if (!streamManagerReady) {
|
||||
String statusResponse = sdkCall("status");
|
||||
String statusResponse = Utils.sdkCall("status");
|
||||
if (statusResponse != null) {
|
||||
JSONObject status = new JSONObject(statusResponse);
|
||||
if (status.has("error")) {
|
||||
|
@ -288,7 +210,7 @@ public class LbrynetService extends PythonService {
|
|||
}
|
||||
|
||||
if (streamManagerReady) {
|
||||
String fileList = sdkCall("file_list");
|
||||
String fileList = Utils.sdkCall("file_list");
|
||||
if (fileList != null) {
|
||||
JSONObject response = new JSONObject(fileList);
|
||||
if (!response.has("error")) {
|
||||
|
@ -309,7 +231,7 @@ public class LbrynetService extends PythonService {
|
|||
try {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("outpoint", outpoint);
|
||||
return sdkCall("file_list", params);
|
||||
return Utils.sdkCall("file_list", params);
|
||||
} catch (ConnectException ex) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,14 @@ import io.lbry.browser.BuildConfig;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
|
@ -21,6 +28,7 @@ import java.security.NoSuchProviderException;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
|
@ -28,8 +36,11 @@ import javax.crypto.CipherOutputStream;
|
|||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
public final class Utils {
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONException;
|
||||
|
||||
public final class Utils {
|
||||
|
||||
private static final String TAG = Utils.class.getName();
|
||||
|
||||
private static final String AES_MODE = "AES/ECB/PKCS7Padding";
|
||||
|
@ -45,7 +56,9 @@ public final class Utils {
|
|||
private static final String SP_ENCRYPTION_KEY = "key";
|
||||
|
||||
private static final String SP_API_SECRET_KEY = "api_secret";
|
||||
|
||||
|
||||
public static final String SDK_URL = "http://127.0.0.1:5279";
|
||||
|
||||
public static String getAndroidRelease() {
|
||||
return android.os.Build.VERSION.RELEASE;
|
||||
}
|
||||
|
@ -242,6 +255,105 @@ public final class Utils {
|
|||
|
||||
return ks;
|
||||
}
|
||||
|
||||
public static String performRequest(String url) throws ConnectException {
|
||||
return performRequest(url, "GET", null);
|
||||
}
|
||||
|
||||
public static String performRequest(String requestUrl, String requestMethod, String json) throws ConnectException {
|
||||
BufferedReader reader = null;
|
||||
DataOutputStream dos = null;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(requestUrl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setDoInput(true);
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestMethod(requestMethod);
|
||||
if ("POST".equals(requestMethod)) {
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-type", "application/json");
|
||||
}
|
||||
|
||||
if (json != null) {
|
||||
dos = new DataOutputStream(conn.getOutputStream());
|
||||
dos.writeBytes(json);
|
||||
dos.flush();
|
||||
dos.close();
|
||||
}
|
||||
|
||||
if (conn.getResponseCode() == 200) {
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String input;
|
||||
while ((input = reader.readLine()) != null) {
|
||||
sb.append(input);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
} else {
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String error;
|
||||
while ((error = reader.readLine()) != null) {
|
||||
sb.append(error);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
} catch (ConnectException ex) {
|
||||
// unable to connect. rethrow
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, ex.getMessage(), ex);
|
||||
// pass
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, ex.getMessage(), ex);
|
||||
// pass
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String sdkCall(String method) throws ConnectException {
|
||||
return sdkCall(method, null);
|
||||
}
|
||||
|
||||
public static String sdkCall(String method, Map<String, String> params) throws ConnectException {
|
||||
try {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("method", method);
|
||||
if (params != null) {
|
||||
JSONObject requestParams = new JSONObject();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
requestParams.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
request.put("params", requestParams);
|
||||
}
|
||||
|
||||
return performRequest(SDK_URL, "POST", request.toString());
|
||||
} catch (ConnectException ex) {
|
||||
// sdk not started yet. rethrow
|
||||
throw ex;
|
||||
} catch (JSONException ex) {
|
||||
// normally shouldn't happen
|
||||
Log.e(TAG, ex.getMessage(), ex);
|
||||
// pass
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static byte[] rsaEncrypt(byte[] secret, KeyStore keyStore) throws Exception {
|
||||
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
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;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import io.lbry.browser.MainActivity;
|
||||
import io.lbry.browser.Utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class RequestsModule extends ReactContextBaseJavaModule {
|
||||
private Context context;
|
||||
|
||||
public RequestsModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.context = reactContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Requests";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void get(final String url, final Promise promise) {
|
||||
(new AsyncTask<Void, Void, String>() {
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
try {
|
||||
return Utils.performRequest(url);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onPostExecute(String response) {
|
||||
if (response == null) {
|
||||
promise.reject(String.format("Request to %s returned null.", url));
|
||||
return;
|
||||
}
|
||||
|
||||
promise.resolve(response);
|
||||
}
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void lbryioCall(String authToken, final Promise promise) {
|
||||
// get the auth token here, or let the app pass it in?
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void lbryCall(final Promise promise) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
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;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import io.lbry.browser.MainActivity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class StatePersistorModule extends ReactContextBaseJavaModule {
|
||||
private Context context;
|
||||
|
||||
private List<ReadableMap> queue;
|
||||
|
||||
private ReadableMap filter;
|
||||
|
||||
private ReadableMap lastState;
|
||||
|
||||
private AsyncTask persistTask;
|
||||
|
||||
public StatePersistorModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.context = reactContext;
|
||||
queue = new ArrayList<ReadableMap>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "StatePersistor";
|
||||
}
|
||||
|
||||
/*private WritableMap filterState(ReadableMap state) {
|
||||
WritableMap filteredState = Arguments.createMap();
|
||||
|
||||
return state;
|
||||
}*/
|
||||
|
||||
public boolean hasStateChanged(ReadableMap newState) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void update(ReadableMap state, ReadableMap filter) {
|
||||
if (this.filter == null) {
|
||||
this.filter = filter;
|
||||
}
|
||||
// process state updates from the queue using a background task
|
||||
synchronized (this) {
|
||||
queue.add(state);
|
||||
}
|
||||
persistState();
|
||||
}
|
||||
|
||||
private void persistState() {
|
||||
persistState(false);
|
||||
}
|
||||
|
||||
private void persistState(final boolean flush) {
|
||||
if (flush && persistTask != null) {
|
||||
persistTask.cancel(true);
|
||||
persistTask = null;
|
||||
}
|
||||
|
||||
if (persistTask == null) {
|
||||
persistTask = (new AsyncTask<Object, Void, Boolean>() {
|
||||
protected Boolean doInBackground(Object... param) {
|
||||
// get the first item in the queue
|
||||
ReadableMap queuedState = null;
|
||||
if (queue.size() > 0) {
|
||||
synchronized (StatePersistorModule.this) {
|
||||
queuedState = queue.remove(flush ? queue.size() - 1 : 0);
|
||||
if (flush) {
|
||||
// we only want the final state in this scenario
|
||||
queue.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (queuedState != null) {
|
||||
ReadableMap state = queuedState; //(ReadableMap) filterState(queuedState);
|
||||
// convert to JSON object
|
||||
|
||||
try {
|
||||
JSONObject json = readableMapToJSON(state);
|
||||
|
||||
// save the state file
|
||||
// TODO: explore this option at a later date
|
||||
throw new UnsupportedOperationException();
|
||||
} catch (JSONException ex) {
|
||||
// normally shouldn't happen, but if it does, reinsert into the queue
|
||||
if (queuedState != null) {
|
||||
synchronized (StatePersistorModule.this) {
|
||||
queue.add(0, queuedState);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onPostExecute(Boolean result) {
|
||||
if (queue.size() > 0) {
|
||||
persistState();
|
||||
}
|
||||
|
||||
persistTask = null;
|
||||
}
|
||||
});
|
||||
persistTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void flush() {
|
||||
persistState(true);
|
||||
}
|
||||
|
||||
private static JSONObject readableMapToJSON(ReadableMap readableMap) throws JSONException {
|
||||
JSONObject json = new JSONObject();
|
||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||
while (iterator.hasNextKey()) {
|
||||
String key = iterator.nextKey();
|
||||
switch (readableMap.getType(key)) {
|
||||
case Map:
|
||||
json.put(key, readableMapToJSON(readableMap.getMap(key)));
|
||||
break;
|
||||
case Array:
|
||||
json.put(key, readableArrayToJSON(readableMap.getArray(key)));
|
||||
break;
|
||||
case Boolean:
|
||||
json.put(key, readableMap.getBoolean(key));
|
||||
break;
|
||||
case Null:
|
||||
json.put(key, JSONObject.NULL);
|
||||
break;
|
||||
case Number:
|
||||
json.put(key, readableMap.getDouble(key));
|
||||
break;
|
||||
case String:
|
||||
json.put(key, readableMap.getString(key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private static JSONArray readableArrayToJSON(ReadableArray readableArray) throws JSONException {
|
||||
JSONArray array = new JSONArray();
|
||||
for (int i = 0; i < readableArray.size(); i++) {
|
||||
switch (readableArray.getType(i)) {
|
||||
case Null:
|
||||
break;
|
||||
case Boolean:
|
||||
array.put(readableArray.getBoolean(i));
|
||||
break;
|
||||
case Number:
|
||||
array.put(readableArray.getDouble(i));
|
||||
break;
|
||||
case String:
|
||||
array.put(readableArray.getString(i));
|
||||
break;
|
||||
case Map:
|
||||
array.put(readableMapToJSON(readableArray.getMap(i)));
|
||||
break;
|
||||
case Array:
|
||||
array.put(readableArrayToJSON(readableArray.getArray(i)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
|
@ -10,9 +10,11 @@ import io.lbry.browser.reactmodules.DaemonServiceControlModule;
|
|||
import io.lbry.browser.reactmodules.FirstRunModule;
|
||||
import io.lbry.browser.reactmodules.FirebaseModule;
|
||||
import io.lbry.browser.reactmodules.GalleryModule;
|
||||
import io.lbry.browser.reactmodules.RequestsModule;
|
||||
import io.lbry.browser.reactmodules.ScreenOrientationModule;
|
||||
import io.lbry.browser.reactmodules.StatePersistorModule;
|
||||
import io.lbry.browser.reactmodules.VersionInfoModule;
|
||||
import io.lbry.browser.reactmodules.UtilityModule;;
|
||||
import io.lbry.browser.reactmodules.UtilityModule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -33,7 +35,9 @@ public class LbryReactPackage implements ReactPackage {
|
|||
modules.add(new FirstRunModule(reactContext));
|
||||
modules.add(new FirebaseModule(reactContext));
|
||||
modules.add(new GalleryModule(reactContext));
|
||||
modules.add(new RequestsModule(reactContext));
|
||||
modules.add(new ScreenOrientationModule(reactContext));
|
||||
modules.add(new StatePersistorModule(reactContext));
|
||||
modules.add(new UtilityModule(reactContext));
|
||||
modules.add(new VersionInfoModule(reactContext));
|
||||
|
||||
|
|
Loading…
Reference in a new issue