1 // Copyright 2015-present 650 Industries. All rights reserved. 2 package host.exp.exponent 3 4 import android.Manifest 5 import android.app.Activity 6 import android.app.ActivityManager.RecentTaskInfo 7 import android.content.Intent 8 import android.content.pm.PackageManager 9 import android.os.Bundle 10 import android.os.Handler 11 import androidx.core.content.ContextCompat 12 import host.exp.exponent.di.NativeModuleDepsProvider 13 import host.exp.exponent.kernel.Kernel 14 import host.exp.expoview.BuildConfig 15 import javax.inject.Inject 16 17 // This activity is transparent. It uses android:style/Theme.Translucent.NoTitleBar. 18 // Calls finish() once it is done processing Intent. 19 class LauncherActivity : Activity() { 20 @Inject 21 lateinit var kernel: Kernel 22 onCreatenull23 override fun onCreate(savedInstanceState: Bundle?) { 24 super.onCreate(savedInstanceState) 25 if (BuildConfig.DEBUG) { 26 // Need WRITE_EXTERNAL_STORAGE for method tracing 27 if (Constants.DEBUG_METHOD_TRACING) { 28 if (ContextCompat.checkSelfPermission( 29 this, 30 Manifest.permission.WRITE_EXTERNAL_STORAGE 31 ) != PackageManager.PERMISSION_GRANTED 32 ) { 33 requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 123) 34 } 35 } 36 } 37 NativeModuleDepsProvider.instance.inject(LauncherActivity::class.java, this) 38 39 // Kernel's JS needs to be started for the dev menu to work when the app is launched through the deep link. 40 kernel.startJSKernel(this) 41 kernel.handleIntent(this, intent) 42 43 // Start a service to keep our process awake. This isn't necessary most of the time, but 44 // if the user has "Don't keep activities" on it's possible for the process to exit in between 45 // finishing this activity and starting the BaseExperienceActivity. 46 startService(ExponentIntentService.getActionStayAwake(applicationContext)) 47 48 // Delay to prevent race condition where finish() is called before service starts. 49 Handler(mainLooper).postDelayed( 50 Runnable { 51 try { 52 // Crash with NoSuchFieldException instead of hard crashing at task.getTaskInfo().numActivities 53 RecentTaskInfo::class.java.getDeclaredField("numActivities") 54 for (task in kernel.tasks) { 55 if (task.taskInfo.id == taskId) { 56 if (task.taskInfo.numActivities == 1) { 57 finishAndRemoveTask() 58 return@Runnable 59 } else { 60 break 61 } 62 } 63 } 64 } catch (e: Exception) { 65 // just go straight to finish() 66 } 67 finish() 68 }, 69 100 70 ) 71 } 72 onNewIntentnull73 public override fun onNewIntent(intent: Intent) { 74 super.onNewIntent(intent) 75 76 // We shouldn't ever get here, since we call finish() in onCreate. Just want to be safe 77 // since this Activity is singleTask and there might be some edge case where this is called. 78 kernel.handleIntent(this, intent) 79 } 80 } 81