Packages
mob_new
0.1.23
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.45
0.1.44
0.1.43
0.1.42
0.1.40
0.1.33
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Project generator for the Mob mobile framework
Current section
Files
Jump to
Current section
Files
priv/templates/mob.new/android/app/src/main/java/MainActivity.kt.eex
package <%= java_package %>
import android.app.Activity
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.core.content.FileProvider
import java.io.File
class MainActivity : ComponentActivity() {
companion object {
private const val TAG = "<%= display_name %>"
init { System.loadLibrary("<%= lib_name %>") }
}
external fun nativeSetActivity(activity: Activity)
external fun nativeStartBeam()
// ── Camera launchers ──────────────────────────────────────────────────
private var cameraPhotoUri: Uri? = null
private val cameraPhotoLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
MobBridge.handleCameraPhotoResult(if (success) cameraPhotoUri else null)
}
private val cameraVideoLauncher =
registerForActivityResult(ActivityResultContracts.CaptureVideo()) { success ->
MobBridge.handleCameraVideoResult(if (success) cameraPhotoUri else null)
}
fun launchCameraPhoto() {
val file = File(cacheDir, "mob_cam_${System.currentTimeMillis()}.jpg")
cameraPhotoUri = FileProvider.getUriForFile(this, "$packageName.fileprovider", file)
cameraPhotoLauncher.launch(cameraPhotoUri!!)
}
fun launchCameraVideo() {
val file = File(cacheDir, "mob_cam_${System.currentTimeMillis()}.mp4")
cameraPhotoUri = FileProvider.getUriForFile(this, "$packageName.fileprovider", file)
cameraVideoLauncher.launch(cameraPhotoUri!!)
}
// ── Photo picker launcher ─────────────────────────────────────────────
private val photosPickerLauncher =
registerForActivityResult(ActivityResultContracts.PickMultipleVisualMedia()) { uris ->
MobBridge.handlePhotosResult(uris)
}
fun launchPhotosPicker(max: Int) {
photosPickerLauncher.launch(
androidx.activity.result.PickVisualMediaRequest(
androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.ImageAndVideo
)
)
}
// ── File picker launcher ──────────────────────────────────────────────
private val filePickerLauncher =
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { uris ->
MobBridge.handleFilesResult(uris)
}
fun launchFilePicker() {
filePickerLauncher.launch(arrayOf("*/*"))
}
// ── QR scanner launcher ───────────────────────────────────────────────
// For QR scanning we use an intent to a helper activity (MobScannerActivity)
// that uses CameraX + ML Kit. It returns the scanned value as a result string.
private val scannerLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val value = result.data?.getStringExtra("scan_value")
val type = result.data?.getStringExtra("scan_type") ?: "qr"
MobBridge.handleScanResult(value, type)
}
fun launchQrScanner() {
val intent = android.content.Intent(this, MobScannerActivity::class.java)
scannerLauncher.launch(intent)
}
// ── Permission result ─────────────────────────────────────────────────
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 9001) {
val granted = grantResults.isNotEmpty() &&
grantResults.all { it == PackageManager.PERMISSION_GRANTED }
MobBridge.onPermissionResult(granted)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MobBridge.init(this)
// Check if launched from a notification tap
intent?.extras?.getString("mob_notification_json")?.let { json ->
MobBridge.setLaunchNotification(json)
}
setContent {
val state by MobBridge.rootState
BackHandler(enabled = state.node != null) { MobBridge.nativeHandleBack() }
AnimatedContent(
targetState = state,
contentKey = { it.navKey },
transitionSpec = {
when (targetState.transition) {
"push" ->
slideInHorizontally(animationSpec = tween(300)) { it } togetherWith
slideOutHorizontally(animationSpec = tween(300)) { -it / 3 }
"pop" ->
slideInHorizontally(animationSpec = tween(300)) { -it / 3 } togetherWith
slideOutHorizontally(animationSpec = tween(300)) { it }
"reset" ->
fadeIn(animationSpec = tween(250)) togetherWith
fadeOut(animationSpec = tween(250))
else ->
EnterTransition.None togetherWith ExitTransition.None
}
},
label = "nav"
) { s ->
s.node?.let { RenderNode(it, modifier = Modifier.fillMaxSize()) }
}
}
Log.i(TAG, "onCreate — handing off to BEAM")
nativeSetActivity(this)
Thread({ nativeStartBeam() }, "beam-main").start()
}
}