1 package io.keybase.ossifrage; 2 3 import android.app.Application; 4 import android.content.Context; 5 6 import androidx.multidex.MultiDex; 7 8 import com.evernote.android.job.JobManager; 9 import com.facebook.react.PackageList; 10 import com.facebook.react.ReactApplication; 11 import com.rnim.rn.audio.ReactNativeAudioPackage; 12 import com.facebook.react.ReactNativeHost; 13 import com.facebook.react.ReactPackage; 14 import com.facebook.react.bridge.NativeModule; 15 import com.facebook.react.bridge.ReactApplicationContext; 16 import com.facebook.soloader.SoLoader; 17 18 import org.unimodules.adapters.react.ModuleRegistryAdapter; 19 import org.unimodules.adapters.react.ReactAdapterPackage; 20 import org.unimodules.adapters.react.ReactModuleRegistryProvider; 21 import org.unimodules.core.interfaces.Package; 22 23 // import java.lang.reflect.InvocationTargetException; 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.List; 27 28 import expo.modules.barcodescanner.BarCodeScannerPackage; 29 import expo.modules.constants.ConstantsPackage; 30 import expo.modules.contacts.ContactsPackage; 31 import expo.modules.imagepicker.ImagePickerPackage; 32 import expo.modules.permissions.PermissionsPackage; 33 import expo.modules.sms.SMSPackage; 34 import io.keybase.ossifrage.modules.BackgroundJobCreator; 35 import io.keybase.ossifrage.modules.BackgroundSyncJob; 36 import io.keybase.ossifrage.modules.NativeLogger; 37 import io.keybase.ossifrage.modules.StorybookConstants; 38 39 import static keybase.Keybase.forceGC; 40 41 public class MainApplication extends Application implements ReactApplication { 42 private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(Arrays.<Package>asList( 43 new ReactAdapterPackage(), 44 new ConstantsPackage(), 45 // Same order as package.json 46 new BarCodeScannerPackage(), 47 new ContactsPackage(), 48 new ImagePickerPackage(), 49 new PermissionsPackage(), 50 new SMSPackage() 51 ), null); 52 53 54 @Override attachBaseContext(Context base)55 protected void attachBaseContext(Context base) { 56 super.attachBaseContext(base); 57 MultiDex.install(this); 58 } 59 60 @Override onCreate()61 public void onCreate() { 62 NativeLogger.info("MainApplication created"); 63 super.onCreate(); 64 SoLoader.init(this, /* native exopackage */ false); 65 // initializeFlipper(this); // Remove this line if you don't want Flipper enabled 66 JobManager manager = JobManager.create(this); 67 manager.addJobCreator(new BackgroundJobCreator()); 68 69 // Make sure exactly one background job is scheduled. 70 int numBackgroundJobs = manager.getAllJobRequestsForTag(BackgroundSyncJob.TAG).size(); 71 if (numBackgroundJobs == 0) { 72 BackgroundSyncJob.scheduleJob(); 73 } else if (numBackgroundJobs > 1) { 74 manager.cancelAllForTag(BackgroundSyncJob.TAG); 75 BackgroundSyncJob.scheduleJob(); 76 } 77 } 78 79 @Override onLowMemory()80 public void onLowMemory() { 81 forceGC(); 82 super.onLowMemory(); 83 } 84 85 /** 86 * Loads Flipper in React Native templates. 87 * 88 * @param context 89 */ 90 // private static void initializeFlipper(Context context) { 91 // if (BuildConfig.DEBUG) { 92 // try { 93 // [> 94 // We use reflection here to pick up the class that initializes Flipper, 95 // since Flipper library is not available in release mode 96 // */ 97 // Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper"); 98 // aClass.getMethod("initializeFlipper", Context.class).invoke(null, context); 99 // } catch (ClassNotFoundException e) { 100 // e.printStackTrace(); 101 // } catch (NoSuchMethodException e) { 102 // e.printStackTrace(); 103 // } catch (IllegalAccessException e) { 104 // e.printStackTrace(); 105 // } catch (InvocationTargetException e) { 106 // e.printStackTrace(); 107 // } 108 // } 109 // } 110 111 private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 112 113 @Override 114 public boolean getUseDeveloperSupport() { 115 return BuildConfig.DEBUG; 116 } 117 118 @Override 119 protected List<ReactPackage> getPackages() { 120 Context context = getApplicationContext(); 121 // limit fresco memory 122 // ImagePipelineConfig frescoConfig = ImagePipelineConfig 123 // .newBuilder(context) 124 // .setBitmapMemoryCacheParamsSupplier(new CustomBitmapMemoryCacheParamsSupplier(context)) 125 // .build(); 126 // 127 // MainPackageConfig appConfig = new MainPackageConfig.Builder().setFrescoConfig(frescoConfig).build(); 128 129 @SuppressWarnings("UnnecessaryLocalVariable") 130 List<ReactPackage> packages = new PackageList(this).getPackages(); 131 // new MainReactPackage(appConfig),// removed from rn-diff but maybe we need it for fresco config? 132 packages.add(new KBReactPackage() { 133 @Override 134 public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) { 135 if (BuildConfig.BUILD_TYPE == "storyBook") { 136 List<NativeModule> modules = new ArrayList<>(); 137 modules.add(new StorybookConstants(reactApplicationContext)); 138 return modules; 139 } else { 140 return super.createNativeModules(reactApplicationContext); 141 } 142 } 143 }); 144 145 packages.add(new ModuleRegistryAdapter(mModuleRegistryProvider)); 146 147 return packages; 148 } 149 @Override 150 protected String getJSMainModuleName() { 151 // This is a mildly hacky solution to mock out some code when we're in storybook mode. 152 // The code that handles this is in `shared/metro.config.js`. 153 if (BuildConfig.BUILD_TYPE == "storyBook") { 154 return "storybook-index"; 155 } else { 156 return "normal-index"; 157 } 158 } 159 }; 160 161 @Override getReactNativeHost()162 public ReactNativeHost getReactNativeHost() { 163 return mReactNativeHost; 164 } 165 } 166