This shows you the differences between two versions of the page.
smd:laboratoare:02 [2021/03/24 22:32] adriana.draghici |
smd:laboratoare:02 [2021/03/25 20:41] (current) adriana.draghici [Task 3 - Make a call (1p)] |
||
---|---|---|---|
Line 19: | Line 19: | ||
An Intent is an object of type [[https://developer.android.com/reference/android/content/Intent.html|android.content.Intent]]. This is sent as a parameter for methods, [[https://developer.android.com/reference/android/content/Context.html#startActivity(android.content.Intent)|startActivity()]], [[https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent)|startService()]] or [[https://developer.android.com/reference/android/content/Context.html#sendBroadcast(android.content.Intent)|sendBroadcast()]], for starting an activity, a service or sending a broadcast message. The intent can transmit data to the components via a [[https://developer.android.com/reference/android/os/Bundle|Bundle]] object. | An Intent is an object of type [[https://developer.android.com/reference/android/content/Intent.html|android.content.Intent]]. This is sent as a parameter for methods, [[https://developer.android.com/reference/android/content/Context.html#startActivity(android.content.Intent)|startActivity()]], [[https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent)|startService()]] or [[https://developer.android.com/reference/android/content/Context.html#sendBroadcast(android.content.Intent)|sendBroadcast()]], for starting an activity, a service or sending a broadcast message. The intent can transmit data to the components via a [[https://developer.android.com/reference/android/os/Bundle|Bundle]] object. | ||
+ | |||
+ | ==== Example explicit intent ==== | ||
+ | Launch another activity using an explicit intent. | ||
+ | <code Java> | ||
+ | Intent intent = new Intent( | ||
+ | context, // Application context | ||
+ | Activity.class); // Component name | ||
+ | startActivity(intent); // Launch component | ||
+ | </code> | ||
+ | |||
+ | ==== Example implicit intent ==== | ||
+ | |||
+ | Open an url in your phone's browser using an implicit intent - not specifying the exact app which will open the url, only tell the system that it need to be opened. | ||
+ | |||
+ | <code Java> | ||
+ | Intent intent = new Intent(Intent.ACTION_VIEW); // We've set the ACTION | ||
+ | intent.setData(Uri.parse("https://ocw.cs.pub.ro/smd/lab2"); // We've set DATA | ||
+ | |||
+ | // We check before if an application that can support our intent exists. | ||
+ | // This blocks the app from crashing. We should inform the user about | ||
+ | // this or to disable this feature in our app. | ||
+ | if(intent.resolveActivity(getPackageManager())!=null) { | ||
+ | startActivity(intent); | ||
+ | } | ||
+ | </code> | ||
Line 95: | Line 120: | ||
* **DIAL** - dial a number specified in the data | * **DIAL** - dial a number specified in the data | ||
* **CALL** - directly perform a call | * **CALL** - directly perform a call | ||
- | * **PICK** for activities - to pick an item from the data an return it | + | |
You can have actions defined in other classes, such as [[https://developer.android.com/reference/android/provider/AlarmClock|AlarmClock]] with actions for managing the alarms | You can have actions defined in other classes, such as [[https://developer.android.com/reference/android/provider/AlarmClock|AlarmClock]] with actions for managing the alarms | ||
Line 143: | Line 168: | ||
intent.putExtra("sms_body","Important message.."); // add extra for the sms content | intent.putExtra("sms_body","Important message.."); // add extra for the sms content | ||
</code> | </code> | ||
- | **Flags** | ||
- | === Example explicit intent === | ||
- | |||
- | <code Java> | ||
- | Intent intent = new Intent( | ||
- | context, // Application context | ||
- | Activity.class); // Component name | ||
- | startActivity(intent); // Launch component | ||
- | </code> | ||
- | |||
- | === Example implicit intent === | ||
- | |||
- | <code Java> | ||
- | Intent intent = new Intent(Intent.ACTION_VIEW); // We've set the ACTION | ||
- | setData(Uri.parse("https://ocw.cs.pub.ro/smd/lab2"); // We've set DATA | ||
- | |||
- | // We check before if an application that can support our intent exists. | ||
- | // This blocks the app from crashing. We should inform the user about | ||
- | // this or to disable this feature in our app. | ||
- | if(intent.resolveActivity(getPackageManager())!=null) { | ||
- | startActivity(intent); | ||
- | } | ||
- | </code> | ||
- | |||
- | |||
- | <note important> Your app will crash if there is no app on device that can receive the implicit intents it sends. Make sure to check if any app is available like in the above example.</note> | ||
==== App chooser ==== | ==== App chooser ==== | ||
Line 183: | Line 182: | ||
startActivity(intentChooser); | startActivity(intentChooser); | ||
} | } | ||
+ | |||
</code> | </code> | ||
+ | <note important> Your app will crash if there is no app on device that can receive the implicit intents it sends. Make sure to check if any app is available like in the above example.</note> | ||
==== Task 2 - Go to a web page (1p) ==== | ==== Task 2 - Go to a web page (1p) ==== | ||
Line 202: | Line 203: | ||
<code> | <code> | ||
Intent intent = new Intent(Intent.ACTION_DIAL); | Intent intent = new Intent(Intent.ACTION_DIAL); | ||
- | intent.setData(Uri.parse("tel:"+"enter the phonenumber"); | + | intent.setData(Uri.parse("tel:"+"enter the phonenumber")); |
startActivity(intent); | startActivity(intent); | ||
</code> | </code> | ||
Line 210: | Line 211: | ||
==== Task 4 - Send an email (2p) ==== | ==== Task 4 - Send an email (2p) ==== | ||
- | <note> For this task you need to have configured in your emulators email client an email address or to run the app on a phone which has been already configured</note> | + | <note> For this task you need to have configured in your emulator's email client an email address or to run the app on a phone which has been already configured</note> |
Now we are going to send an email. Edit the fields below with the receiver email, title and subject. The text of the email will be from the MainActivity EditText. Get a reference to "Send email" button and add a click listener as in the previous tasks. | Now we are going to send an email. Edit the fields below with the receiver email, title and subject. The text of the email will be from the MainActivity EditText. Get a reference to "Send email" button and add a click listener as in the previous tasks. | ||
Line 233: | Line 234: | ||
==== Task 5 - Get data from an activity (2p) ==== | ==== Task 5 - Get data from an activity (2p) ==== | ||
- | Usually activities are not started to only receive data they can also be started for returning data. | + | In this task we start an activity and and also receive data from it. |
- | Create a third activity in the project and add an EditText and a Button. In MainActivity, get a reference to //"Get data from activity"// button which will start the third activity. We will use [[https://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent,%20int)|startActivityForResult()]] in order to start the activity. | + | Create a **third activity** in the project and add an EditText and a Button. In ''MainActivity'', get a reference to //"Get data from activity"// button which will start the third activity. We will use [[https://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent,%20int)|startActivityForResult()]] in order to start the activity. |
<code> | <code> | ||
Line 257: | Line 258: | ||
</code> | </code> | ||
- | In the third activity get a reference to the added Buttton and write a click listener in which we take the text from the EditText and send it to the activity that started it. We do this by adding the text into a simple Intent object and by setting the wanted result code. In order to close this activity will call **finish()**. | + | In the third activity get a reference to the added Button and write a click listener in which we take the text from the EditText and send it to the activity that started it. We do this by adding the text into a simple Intent object and by setting the wanted result code. In order to close this activity will call **finish()**. |
<code> | <code> | ||
Line 279: | Line 280: | ||
* **<category>** - intent category, represented by a string value. | * **<category>** - intent category, represented by a string value. | ||
- | Example intent filter: | + | **Example:** |
<code> | <code> | ||
Line 291: | Line 292: | ||
</code> | </code> | ||
- | Multiple action, category, data can be used in an intent filter or multiple intent filters can be defined. For both cases, the corresponding component must be checked if it can handle all of the defined intents. | + | Multiple actions, categories and data can be used in an intent filter and an activity can contain multiple intent filters. |
- | /* | ||
- | <note warning>As a security feature to do is not to declare intent-filters for components used just inside the app. You should use explicit intent for those. Intent-filters can be used by another app if it determines the exact name of the component. Then it can use explicit intents to start it.</note> | ||
- | */ | ||
- | If we need to define an intent filter for just a period of time for a broadcast receiver, we can do it by registering it dynamically. **registerReceiver()** and **unregisterReceiver()** are used for registering and unregistering. | + | <note warning>For security reasons you should avoid declaring intent-filters for components used just inside the app. You should use explicit intent for actions internal to your app. The reason is that intent-filters need to be declared in the manifest, therefore visible to anyone. A malicious app can then start your exported components (obtaining their names is not that difficult) using explicit intents</note> |
+ | |||
+ | If we need to define an intent filter for just a period of time for a broadcast receiver, we can do it by **registering it dynamically**. | ||
===== Broadcast Receivers ===== | ===== Broadcast Receivers ===== | ||
Line 312: | Line 312: | ||
<code> | <code> | ||
<receiver android:name=".MyReceiver" | <receiver android:name=".MyReceiver" | ||
- | android:exported="true/false" // accesible/not accesible by other applications with different used id | + | android:exported="true/false" // accessible/not accessible by other applications with different used id |
android:enabled="true/false" /> // can/cannot be registered by the system | android:enabled="true/false" /> // can/cannot be registered by the system | ||
</code> | </code> | ||
Line 392: | Line 392: | ||
<note important>Do not use broadcast receivers to maintain state or to be interacted with. It "lives" only until the //onReceive// method finishes. Also, do not forget to register and unregister your broadcast receiver in the activity's lifecycle callbacks, e.g. in onPause and onResume.</note> | <note important>Do not use broadcast receivers to maintain state or to be interacted with. It "lives" only until the //onReceive// method finishes. Also, do not forget to register and unregister your broadcast receiver in the activity's lifecycle callbacks, e.g. in onPause and onResume.</note> | ||
+ | ===== Summary ===== | ||
+ | |||
+ | * Intents facilitate communication between android components (activities, services etc) | ||
+ | * Two types of intents: | ||
+ | * explicit: contains the destination | ||
+ | * implicit: sent to the system and the system find an application that can handle the action. If it doesn't, the app crashes. | ||
+ | * Intent filters: | ||
+ | * define which intents a component can handle (the component can be an activity) | ||
+ | * Broadcast receivers: | ||
+ | * Android components that can receive messages under the form of intents | ||
+ | * Can receive system broadcasts (e.g. bluetooth connectivity updates) | ||
+ | * Can receive broadcasts from other apps or from inside the same app | ||
+ | * Can be dynamically registered and unregistered or declared in the manifest | ||
+ | |||
+ | |||
+ | <note warning> | ||
+ | **Security concerns summary** | ||
+ | * Make sure to check your manifest for any components marked as exported by default when you created them. This flag tells the system that the component can be invoked by other apps (see [[https://developer.android.com/training/articles/security-tips#BroadcastReceivers|info here]], exploit example on broadcast receivers [[https://resources.infosecinstitute.com/topic/android-hacking-security-part-3-exploiting-broadcast-receivers/|here]]) | ||
+ | * If your broadcast only targets your app, then declare the receivers locally (see LocalBroadcastManager) | ||
+ | * There are limitations to what implicit broadcasts are supported for manifest-declared broadcast receivers (see [[https://developer.android.com/guide/components/broadcasts#manifest-declared-receivers|info here]]) | ||
+ | </note> | ||
===== Links ===== | ===== Links ===== | ||
* [[https://developer.android.com/codelabs/basic-android-kotlin-training-activities-intents?hl=en&continue=https%3A%2F%2Fcodelabs.developers.google.com%2F%3Fcat%3Dandroid|Activity and Intents Codelab]] - easy step by step tutorial to learn about intents | * [[https://developer.android.com/codelabs/basic-android-kotlin-training-activities-intents?hl=en&continue=https%3A%2F%2Fcodelabs.developers.google.com%2F%3Fcat%3Dandroid|Activity and Intents Codelab]] - easy step by step tutorial to learn about intents |