The most important Android components:
Activity: The visible part of your app, displaying View objectsFragment: Allows flexible modularisation of Views within ActivitiesService: Runs code in the background without a ViewContentProvider: Provides data for your appBroadcastReceiver: Used to receive messages between activies or even appsIntent: Allows inter-component communication, used e.g. to start Activities and transfer
information between themAn activity has essentially four states:
class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  }
  override fun onStart() {
    super.onStart()
  }
  override fun onRestart() {
    super.onRestart()
  }
  override fun onResume() {
    super.onResume()
  }
  override fun onPause() {
    super.onPause()
  }
  override fun onStop() {
    super.onStop()
  }
  override fun onDestroy() {
    super.onDestroy()
  }
}class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      ...
    }
  }
  
  ...
}// launches a new activity
abstract void startActivity(Intent intent) 
//launches a new service
abstract ComponentName startService(Intent service) 
//Registers a BroadCast Receiver
abstract Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) val dialIntent = Intent()
dialIntent.action = Intent.ACTION_DIAL //specifiy the action to execute
dialIntent.data = Uri.parse("tel:0711-1234") //provide action data
startActivity(dialIntent)
   
<intent-filter> element in your manifest file. <intent-filter> element in the app's manifest file,
nested in the corresponding app component (such as an <activity> element). <intent-filter>, you can specify the type of intents to accept using one or
more of these three elements:<action> - Declares the intent action accepted, in the name attribute. The value must be the
literal string value of an action, not the class constant.<data> - Declares the type of data accepted, using one or more attributes that specify
various aspects of the data URI (scheme, host, port, path) and MIME type.<category> - Declares the intent category accepted, in the name attribute. The value must be
the literal string value of an action, not the class constant.<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>Note: To receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter.
putExtra() method of the
Intent class can be usedval intent = Intent(applicationContext, LoginActivity::class.java)
intent.putExtra("Name", "Login")
startActivity(intent)Note: An explicit intent is always delivered to its target, regardless of any intent filters the component declares.
Install time verification
Application sandboxing (process separation)
Permissions
INTERNET, READ_CONTACTS,...SecurityExceptions<uses-permission> tags app manifest must be
used    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    ...
</manifest>To request a dangerous permission at runtime, some additional code is required in your Activity class:
// Assume thisActivity is the current activity
val permissionCheck = ContextCompat.checkSelfPermission(LocalContext.current, Manifest.permission.WRITE_CALENDAR)// ...
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(
    LocalContext.current as Activity,
    Manifest.permission.READ_CALENDAR)
) {
    // Show an explanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.
} else {
    // ... see next slide// ...
else {
  val permissionLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
  ) { isGranted ->
    if (isGranted) {
      // Permission granted
    } else {
      // Handle permission denial
    }
  }
  permissionLauncher.launch(Manifest.permission.READ_CONTACTS)
}
// ...val uri = Uri.parse("https://www.google.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
context.startActivity(intent)AndroidView()loadUrl()@Composable
fun WebView() {
  AndroidView(factory = {
    WebView(it).apply {
        //any other configuration
    }
  }, update = {
    it.loadUrl("https://www.google.com")
  })
}<uses-permission android:name="android.permission.INTERNET" />this.webViewClient = WebViewClient()WebViews settings but you also have to add @SuppressLint("SetJavaScriptEnabled") annotation:this.settings.javaScriptEnabled = trueWebChromeClient like this:var currentProgress by remember { mutableStateOf(0f) }
...
this.webChromeClient = object : WebChromeClient() {
  override fun onProgressChanged(view: WebView?, newProgress: Int) {
    super.onProgressChanged(view, newProgress)
    currentProgress = newProgress/100f
  }
}LinearProgressIndicator(progress = { currentProgress }, modifier = Modifier.fillMaxWidth())Note: A progress bar can be used for other purposes too of course.