Differences

This shows you the differences between two versions of the page.

Link to this comparison view

smd:laboratoare:02 [2021/02/28 19:50]
adriana.draghici [Lab 02. Communication between Android components: Intents, Broadcast Receivers]
smd:laboratoare:02 [2021/03/25 20:41] (current)
adriana.draghici [Task 3 - Make a call (1p)]
Line 1: Line 1:
 ====== ​ Lab 02. Communication between Android components: Intents, Broadcast Receivers ====== ====== ​ Lab 02. Communication between Android components: Intents, Broadcast Receivers ======
    
-<note important>​This page hasn't been updated yet for the 2021 semester and may contain outdated information</​note>​ 
  
 ===== Objectives ===== ===== Objectives =====
Line 12: Line 11:
 ===== What are Intents? ===== ===== What are Intents? =====
  
-In Android, applications and application components can interact with one another by using **Intent** objects. An **Intent** is a messaging object used to request an action from another application component. It can be used between components of the same app or from different applications. ​+In Android, applications and application components can interact with one another by using **Intent** objects. An **Intent** is a **messaging** object used to request an action from another application component. It can be used between components of the same app or from different applications. ​
  
-Usually an intent is used for:+Usually ​**an intent is used for**:
   * Launching an activity from the same Android application or other activities from other applications;​   * Launching an activity from the same Android application or other activities from other applications;​
   * For delivering a broadcast message;   * For delivering a broadcast message;
Line 20: 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>​
  
  
 ===== Explicit Intents ===== ===== Explicit Intents =====
  
-They specify the target component name, using the Java class name. Usually ​there are used inside applications. A good example is when an activity starts another activity as presented below:+They specify the target component name, using the Java class name. Usually ​they are used inside applications. A good example is when an activity starts another activity as presented below:
  
 <​code>​ <​code>​
Line 40: Line 64:
 **a) startActivity** **a) startActivity**
  
-Create a new project and replace the content of the activity layout with **activity_main.xml** ​from the lab archive. Get a reference to **"Go to secondary activity"​** button in the onCreate method of MainActivity. Add a new Activity to the project. You can automatically add a new activity by right clicking on the project and selecting **New > Activity > Empty Activity** from the menu. This will start a wizard similar to the one at application creation.+Create a new project and replace the content of the activity layout with **activity_main.xml** ​provided in the [[smd:​laboratoare:​02#​resources|Resources]] section. You can use/make your own layout but make sure it allows you to test all the tasks in this lab. 
 + 
 +Get a reference to **"Go to secondary activity"​** button in the onCreate method of MainActivity. Add a new Activity to the project. You can automatically add a new activity by right clicking on the project and selecting **New > Activity > Empty Activity** from the menu. This will start a wizard similar to the one at application creation.
  
 Back in ''​MainActivity'',​ add code to the onClick of the ''​View.OnClickListener''​ so that the new activity gets started. To start a new Activity you have to create an intent first which will **explicitly** take two parameters: a Context and the Class of the second activity. ​ Back in ''​MainActivity'',​ add code to the onClick of the ''​View.OnClickListener''​ so that the new activity gets started. To start a new Activity you have to create an intent first which will **explicitly** take two parameters: a Context and the Class of the second activity. ​
Line 89: Line 115:
 **Action** **Action**
  
-It is represented by a string that describes the action, for example: +It is represented by a string that describes the action, for example ​some defined in the [[https://​developer.android.com/​reference/​android/​content/​Intent|Intent]] class
-  * **VIEW** - transmit data that can be shown to the user in the activity - phone, ​adress, file+  * **VIEW** - transmit data that can be shown to the user in the activity - phone, ​address, file
   * **SEND** - usually named share intent, in which an app can share data with another   * **SEND** - usually named share intent, in which an app can share data with another
   * **DIAL** - dial a number specified in the data   * **DIAL** - dial a number specified in the data
-  * **CALL** - perform a call +  * **CALL** - directly ​perform a call 
-  * **MAIN** - start as the main entry point, no data is needed + 
-  * **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 
-  * **BOOT_COMPLETED** - used after the phone has finished booting + 
-  * **SHUTDOWN** - the device has shutdown +<code Java> 
-  * **PACKAGE_ADDED** for broadcast receivers - a new package has been installed on the device+Intent intent = new Intent(Intent.ACTION_SENDTO);​ // setting ​the action 
 +</​code>​ 
  
 You can also add custom actions. They respect the same rules by adding the application package name before the name of the action: You can also add custom actions. They respect the same rules by adding the application package name before the name of the action:
Line 108: Line 136:
 **Data** **Data**
  
-Based on the specified action the data field can take different values. In general it is an URI and/or [[https://ro.wikipedia.org/​wiki/​MIME|MIME]] type of the data. The URI is a reference to the data on which the action will be done. If the URIs are similar and the MIME type can not be inferred it should be specified.+Based on the specified action the data field can take different values. In general it is an URI and/or [[https://​wikipedia.org/​wiki/​MIME|MIME]] type of the data. The URI is a reference to the data on which the action will be done. If the URIs are similar and the MIME type can not be inferred it should be specified. 
 + 
 + 
 +<code Java> 
 +Intent intent = new Intent(Intent.ACTION_SENDTO);​ // setting the action 
 +intent.setData(Uri.parse("​smsto:"​));​ // setting the data (this uri can also be specified as second param in the constructor) 
 +</​code>​
  
 These are some standard data fields used in an Intent: These are some standard data fields used in an Intent:
Line 122: Line 156:
 <​note>​If you want that one of your application components to accept implicit intents, you need to add the **DEFAULT** category. Without it the system will not accept that component as handler for an Intent even if it can handle it.</​note>​ <​note>​If you want that one of your application components to accept implicit intents, you need to add the **DEFAULT** category. Without it the system will not accept that component as handler for an Intent even if it can handle it.</​note>​
  
-These properties are enough for defining an Intent. ​Using them the system is able to determine which application component to start. Besides that, an Intent can contain additional information.+<code Java> 
 +intent.addCategory(Intent.CATEGORY_APP_EMAIL);​ // add the category for the activity to be able to send or receive emails 
 +</​code>​
  
 **Extras** **Extras**
Line 128: Line 164:
 Extras are //​key-value//​ pairs which contain additional information needed to finish the specified action. Extra data is added through the **putExtra()** method, using key value pairs or by adding a Bundle object. The Intent class contains **EXTRA*** constants key for different data types. As in the example with custom actions you can create custom extras, using the same method of having the application package as a prefix. Extras are //​key-value//​ pairs which contain additional information needed to finish the specified action. Extra data is added through the **putExtra()** method, using key value pairs or by adding a Bundle object. The Intent class contains **EXTRA*** constants key for different data types. As in the example with custom actions you can create custom extras, using the same method of having the application package as a prefix.
  
-<​code>​ +<​code ​Java
-static final String ​EXTRA_ANDROIDS = "com.smd.lab2.EXTRA_ANDROIDS";+intent.putExtra("​address",​ new String ​("123456789"​));​ // add extra for the phone number 
 +intent.putExtra("​sms_body","​Important message..")// add extra for the sms content
 </​code>​ </​code>​
  
-**Flags** 
- 
-These are needed for specifying metadata needed by the Android system. Check the [[https://​developer.android.com/​reference/​android/​content/​Intent.html#​setFlags(int)|setFlags()]] method. 
- 
-=== Example explicit intent === 
- 
-<​code>​ 
-Intent intent = new Intent( 
-  context, // Application context 
-  Activity.class);​ // Component name  
-startActivity(intent);​ // Launch component 
-</​code>​ 
- 
-=== Example implicit intent === 
- 
-<​code>​ 
-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 there exists an application that can support our intent. ​ 
-// 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>​ 
  
 ==== App chooser ==== ==== App chooser ====
Line 164: Line 175:
  
 <​code>​ <​code>​
-Intent = new Intent(Intent.ACTION_SEND);​+Intent ​intent ​= new Intent(Intent.ACTION_SEND);​
 String chooserTitle = "Share photo with"; String chooserTitle = "Share photo with";
 Intent intentChooser = Intent.createChooser(intent,​ chooserTitle);​ Intent intentChooser = Intent.createChooser(intent,​ chooserTitle);​
Line 171: 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 190: 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 198: 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 221: 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 245: 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 267: 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 279: 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 ​actionscategories 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 not 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 298: 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 354: Line 368:
 ==== Task 6 - Broadcast receivers (2p) ==== ==== Task 6 - Broadcast receivers (2p) ====
  
-Add a Broadcast Receiver to the project **New > Other > Broadcast Receiver** and name it MyReceiver.java. We will want to use this receiver to pop a simple message on the screen when clicking on the **Send text to receiver** button. ​ The message will contain the text inserted in the EditText.+Add a Broadcast Receiver to the project **New > Other > Broadcast Receiver** and name it ''​MyReceiver''​. We will want to use this receiver to pop a simple message on the screen when clicking on the ''​Send text to receiver'' ​button. ​ The message will contain the text inserted in the EditText.
  
-In order to achieve this, create a click listener ​with an Intent containing the context object and the receiver'​s class name. Add the text using //putExtra//. Afterwards, use //sendBroadcast// to send the intent to the BroadcastReceiver.+In order to achieve this, create a ClickListener ​with an Intent containing the context object and the receiver'​s class name. Add the text using ''​putExtra''​. Afterwards, use ''​sendBroadcast'' ​to send the intent to the BroadcastReceiver.
  
 <​code>​ <​code>​
Line 370: Line 384:
 </​code>​ </​code>​
  
-Inside the receiver, in the //onReceive// method, retrieve the String added to the intent and display it using a toast notification.+Inside the receiver, in the ''​onReceive'' ​method, retrieve the String added to the intent and display it using a toast notification.
  
 <​code>​ <​code>​
Line 378: 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 =====
 +  * [[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/​guide/​components/​broadcasts#​security-and-best-practices|Security considerations about Broadcast Receivers]]
 +  * [[https://​developer.android.com/​guide/​components/​intents-filters|Intents documentation and security warnings]]
 ===== Resources ===== ===== Resources =====
- ​{{:​smd:​laboratoare:​lab2.zip}}+Layout: 
 +  {{:​smd:​laboratoare:​lab2.zip}} 
 +  * [[https://​github.com/​SMD-UPB/​labs/​tree/​main/​lab2|Available in the Github repo]]
  
  
smd/laboratoare/02.1614534623.txt.gz · Last modified: 2021/02/28 19:50 by adriana.draghici
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0