lbry.tv hybrid mode (#869)

* lbry.tv experiment build
* add task for checking if the sdk is ready
* fix for special urls
* send onSdkStatusResponse events
* persist dht setting to file system
This commit is contained in:
Akinwale Ariwodola 2020-03-20 08:30:34 +01:00 committed by GitHub
parent 5b165a2339
commit 56c375f344
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 33 deletions

View file

@ -12,10 +12,6 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import io.lbry.browser.receivers.NotificationDeletedReceiver;
import io.lbry.lbrysdk.LbrynetService;

View file

@ -116,7 +116,8 @@ public class LbrynetMessagingService extends FirebaseMessagingService {
} else {
if (!MainActivity.isServiceRunning(this, LbrynetService.class) &&
contentTitle != null &&
channelUrl != null
channelUrl != null &&
!url.startsWith("lbry://?") /* not a special url */
) {
// only enter lite mode when contentTitle and channelUrl are set (and the service isn't running yet)
// cold start

View file

@ -3,6 +3,7 @@ package io.lbry.browser;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@ -18,6 +19,7 @@ import android.content.SharedPreferences;
import android.database.Cursor;
import android.Manifest;
import android.net.Uri;
import android.os.Handler;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.Settings;
@ -62,10 +64,12 @@ import io.lbry.browser.reactpackages.LbryReactPackage;
import io.lbry.browser.reactmodules.BackgroundMediaModule;
import io.lbry.lbrysdk.LbrynetService;
import io.lbry.lbrysdk.ServiceHelper;
import io.lbry.lbrysdk.Utils;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.ConnectException;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -84,51 +88,34 @@ import org.reactnative.camera.RNCameraPackage;
public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
private static Activity currentActivity = null;
private static final int OVERLAY_PERMISSION_REQ_CODE = 101;
private static final int STORAGE_PERMISSION_REQ_CODE = 201;
private static final int PHONE_STATE_PERMISSION_REQ_CODE = 202;
private static final int RECEIVE_SMS_PERMISSION_REQ_CODE = 203;
public static final int DOCUMENT_PICKER_RESULT_CODE = 301;
public static final String SHARED_PREFERENCES_NAME = "LBRY";
public static final String SALT_KEY = "salt";
public static final String DEVICE_ID_KEY = "deviceId";
public static final String SOURCE_NOTIFICATION_ID_KEY = "sourceNotificationId";
public static final String SETTING_KEEP_DAEMON_RUNNING = "keepDaemonRunning";
public static List<Integer> downloadNotificationIds = new ArrayList<Integer>();
private BroadcastReceiver notificationsReceiver;
private BroadcastReceiver smsReceiver;
private BroadcastReceiver stopServiceReceiver;
private BroadcastReceiver downloadEventReceiver;
private FirebaseAnalytics firebaseAnalytics;
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
public static final String SHARED_PREFERENCES_NAME = "LBRY";
public static final String SALT_KEY = "salt";
public static final String DEVICE_ID_KEY = "deviceId";
public static final String SOURCE_NOTIFICATION_ID_KEY = "sourceNotificationId";
public static final String SETTING_KEEP_DAEMON_RUNNING = "keepDaemonRunning";
public static List<Integer> downloadNotificationIds = new ArrayList<Integer>();
/**
* Flag which indicates whether or not the service is running. Will be updated in the
* onResume method.
*/
private boolean serviceRunning;
private CheckSdkReadyTask checkSdkReadyTask;
private boolean lbrySdkReady;
private boolean receivedStopService;
private PermissionListener permissionListener;
protected String getMainComponentName() {
@ -158,12 +145,12 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
// Check the dht setting
SharedPreferences sp = getSharedPreferences(MainActivity.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
LbrynetService.setDHTEnabled(sp.getBoolean(UtilityModule.DHT_ENABLED, false));
serviceRunning = isServiceRunning(this, LbrynetService.class);
if (!serviceRunning) {
CurrentLaunchTiming.setColdStart(true);
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
}
checkSdkReady();
if (LbrynetService.serviceInstance != null) {
// TODO: Add a broadcast receiver to listen for the service started event, so that we can set this properly
@ -203,6 +190,22 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
setContentView(mReactRootView);
}
private void checkSdkReady() {
if (!lbrySdkReady) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (checkSdkReadyTask != null && checkSdkReadyTask.getStatus() != AsyncTask.Status.FINISHED) {
// task already running
return;
}
checkSdkReadyTask = new CheckSdkReadyTask();
checkSdkReadyTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}, 1000);
}
}
private void checkNotificationOpenIntent(Intent intent) {
if (intent != null) {
String notificationName = intent.getStringExtra("notification_name");
@ -477,10 +480,13 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
super.onResume();
SharedPreferences sp = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
LbrynetService.setDHTEnabled(sp.getBoolean(UtilityModule.DHT_ENABLED, false));
serviceRunning = isServiceRunning(this, LbrynetService.class);
if (!serviceRunning) {
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
}
checkSdkReady();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this, this);
@ -684,7 +690,6 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
*/
@SuppressLint("NewApi")
public static String getRealPathFromURI_API19(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
@ -835,6 +840,51 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private class CheckSdkReadyTask extends AsyncTask<Void, Void, Boolean> {
public Boolean doInBackground(Void... params) {
boolean sdkReady = false;
try {
String response = Utils.sdkCall("status");
if (response != null) {
JSONObject result = new JSONObject(response);
JSONObject status = result.getJSONObject("result");
// send status response for splash page updates
WritableMap sdkStatus = JSONObjectToMap(status);
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
WritableMap evtParams = Arguments.createMap();
evtParams.putMap("status", sdkStatus);
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onSdkStatusResponse", evtParams);
}
JSONObject startupStatus = status.getJSONObject("startup_status");
sdkReady = startupStatus.has("stream_manager") && startupStatus.has("wallet") &&
startupStatus.getBoolean("stream_manager") && startupStatus.getBoolean("wallet") &&
(status.getJSONObject("wallet").getLong("blocks_behind") <= 0);
}
} catch (ConnectException ex) {
// pass
} catch (JSONException ex) {
// pass
}
return sdkReady;
}
protected void onPostExecute(Boolean sdkReady) {
lbrySdkReady = sdkReady;
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (sdkReady && reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onSdkReady", null);
}
if (!sdkReady) {
checkSdkReady();
}
}
}
public static class LaunchTiming {
private Date start;

View file

@ -34,6 +34,7 @@ import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@ -93,6 +94,7 @@ public class UtilityModule extends ReactContextBaseJavaModule {
public Map<String, Object> getConstants() {
final Map<String, Object> constants = MapBuilder.newHashMap();
constants.put("language", language);
constants.put("dhtEnabled", LbrynetService.isDHTEnabled());
return constants;
}
@ -422,13 +424,34 @@ public class UtilityModule extends ReactContextBaseJavaModule {
}
@ReactMethod
public void setNativeBooleanSetting(String key, boolean value) {
public void setNativeBooleanSetting(String key, final boolean value) {
if (context != null) {
SharedPreferences sp = context.getSharedPreferences(MainActivity.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(key, value);
editor.commit();
}
if (DHT_ENABLED.equalsIgnoreCase(key)) {
(new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
String fileContent = value ? "on" : "off";
String path = String.format("%s/%s", Utils.getAppInternalStorageDir(context), "dht");
PrintStream out = null;
try {
out = new PrintStream(new FileOutputStream(path));
out.print(fileContent);
} catch (Exception ex) {
// pass
} finally {
if (out != null) {
out.close();
}
}
return null;
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
@ReactMethod