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 Activity : Context() {
protected fun onCreate(savedInstanceState: Bundle?)
protected fun onStart()
protected fun onRestart()
protected fun onResume()
protected fun onPause()
protected fun onStop()
protected fun onDestroy()
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
...
}
// 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
,...SecurityException
s<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(thisActivity, Manifest.permission.WRITE_CALENDAR)
// ...
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(
thisActivity,
Manifest.permission.READ_CONTACTS)
) {
// 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 {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
// ...
fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>?, grantResults: IntArray
) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.size > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return
}
}
}
val uri = Uri.parse("https://www.google.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)
<WebView
android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
val myWebView = findViewById(R.id.webView1) as WebView
myWebView.loadUrl("https://www.google.com")
<uses-permission android:name="android.permission.INTERNET" />
myWebView.webViewClient = object : WebViewClient() {}
WebView
s settings:myWebView.getSettings().setJavaScriptEnabled(true);
WebChromeClient
like this:val myWebView = findViewById(R.id.webView1) as WebView
myWebView.webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView, progress: Int) {
val bar = findViewById(R.id.progressBar) as ProgressBar
bar.progress = progress
}
}
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Note: A progress bar can be used for other purposes too of course.