20Multiple Activities PDF

Title 20Multiple Activities
Author Anon User
Course Object-Oriented Systems Design
Institution Stanford University
Pages 8
File Size 335.3 KB
File Type PDF
Total Downloads 56
Total Views 167

Summary

A guide on Android activities....


Description

Stanford CS108

Handout #20 Young

Multiple Activities So far we’ve limited our Android programming to apps consisting of only a single activity. In this handout we learn how to create apps with many different activities.

Ch Chang ang angin in ingg A Activ ctiv ctiviti iti ities es Most Android applications will consist of multiple activities. For example, an email application might have one activity to display all of a user’s current email messages for a particular email account, a second activity allowing them to compose a message, and possibly a third activity showing them a summary of all of their different email accounts. Changing from one activity to another is actually pretty simple. For our first example, we’ll show a simple application consisting of two activities. The main activity allows the user to type a message into an EditText and make some formatting choices. They will then hit the “Submit” button. This will take them to a second activity which will display the message.

Starting Another Activity Just getting the second activity to start is very simple. Activities in Android are started using something called an Intent. An Intent indicates that the user wants to carry out a particular task. While the intent

generated could be specific to our application it could be a much more general action, not specific to our application, such as a request to create a new calendar event, display a location on a map, or to make a phone call. To start off with, let’s just focus on tasks specific to our application. Here’s what we need to do to go from one activity in our app to another: 1) First, create a second activity. Right-mouse click on the app folder in the “Android Project View” (left-hand pane in Android Studio) and choose “New > Activity > Empty Activity”. This will create a new activity that is almost identical to the Main Activity that we’ve been working with so far. It will include its own Java file identical to the “MainActivity.java” we’ve been using and will also have an XML layout file similar to the activity_main.xml file we’ve been using to do layout. 2) Next, decide what user action is going to cause your app to go from the main activity to your new secondary activity. For our example, we’re just going to have a button on the first activity, with a button event handler that will switch to the second activity. 3) Write the event handling code to switch. 4) Add to the onCreate code of the second activity as needed. Okay, let’s take a look at the actual code. Here’s a very simple example taking us from the main activity to a second activity which I named SecondActivity.java: public void onSubmit(View view) { Intent intent = new Intent(this,SecondActivity.class); startActivity(intent); } onSubmit is our event handler which will execute when the user clicks on the “Submit” button. I’ve connected the event handler to the button using an onClick attribute-value pair in the activity_main.xml (if this doesn’t sound familiar, review the “Basic Android Programming” handout). You can see what we do is create an Intent object, passing in the current activity as a context, and telling it we want to switch to the SecondActivity by passing in a reference to that second activity’s class. Finally we need to start the new activity by calling the startActivity method. Calling startActivity will call the second activity’s onCreate method. The default implementation of the onCreate will use the layout from the second activity’s XML layout file and will display it in the Android device.

Passing Data to an Activity Typically, when one activity starts another activity, we’ll want to pass information from the first activity to the new activity. We can do this by adding data to our Intent using the putExtra method. This will allow us to add a set of attribute-value data pairs to the Intent. putExtra takes two parameters, the first one is always a String which is the name we’ll use to identify our attribute. The second is the value. The putExtra method is overloaded and so the second parameter can take many different values such as Strings, booleans, longs, and even arrays. Here are a couple of examples: Intent putExtra(String name, String value) Intent putExtra(String name, double value)

Intent putExtra(String name, boolean value) Intent putExtra(String name, String[] value) Check here for a full list of variants of putExtra – there are currently over 20 of them: https://developer.android.com/reference/android/content/Intent.html For our sample application here’s how I got the information from the various controls displayed on the first activity and added them to the intent in order to send them on to the second activity: public void onSubmit(View view) { EditText msgEditText = (EditText) findViewById(R.id.message_text); CheckBox italicsCheckBox = (CheckBox) findViewById(R.id.italic_check); RadioGroup colorGroup = (RadioGroup) findViewById(R.id.color_group); String msgString = msgEditText.getText().toString(); boolean useItalics = italicsCheckBox.isChecked(); int color = (colorGroup.getCheckedRadioButtonId() == R.id.red)? Color.RED: Color.BLUE; Intent intent = new Intent(this,SecondActivity.class); intent.putExtra("MESSAGE",msgString); intent.putExtra("USE_ITALICS",useItalics); intent.putExtra("COLOR",color); startActivity(intent); }

Reading Data Passed to an Activity In the onCreate method for the newly initiated activity, we can retrieve the Intent using the getIntent method. We can then retrieve each of the data items we placed into the Intent using putExtra by calling a corresponding get…Extra. In contrast with the overloaded putExtra, there are different versions of get…Extra one for each data type, such as getStringExtra and getDoubleExtra. Here are a few samples – remember these are methods on the Intent, not on the Activity: String getStringExtra(String name) boolean getBooleanExtra(String name, boolean defaultValue) double getDoubleExtra(String name, double defaultValue) String[] getStringArrayExtra(String name) Here’s the code I used in my second activity to get information out of the intent on the message and styling to use and which I ultimately used to output the message string: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.activity_second); Intent intent = getIntent(); String msgString = intent.getStringExtra("MESSAGE"); boolean useItalics = intent.getBooleanExtra("USE_ITALICS", false); int color = intent.getIntExtra("COLOR",Color.BLACK); TextView outputView = (TextView) findViewById(R.id.output_text); if (useItalics) { outputView.setTypeface(Typeface.DEFAULT,Typeface.ITALIC); } else { outputView.setTypeface(Typeface.DEFAULT); } outputView.setTextColor(color); outputView.setText(msgString); }

Using String Constants One shortcoming of the code I’ve shown above is it depends on the programmer matching String values in both activities. This is error-prone and the system has no way of checking if you’ve mistyped one of the Strings. One common way of getting around this is to specify the Strings as constants in one of the activities and then have both the putExtra methods and the get…Extra methods refer to the constants. For our example, I could define the constants at the top level of the MainActivity.java like this: public static final String MESSAGE_EXTRA = "MESSAGE"; public static final String USE_ITALICS_EXTRA = "USE_ITALICS"; public static final String USE_COLOR_EXTRA = "COLOR"; Now my putExtras would look something like this: intent.putExtra(MESSAGE_EXTRA,msgString); intent.putExtra(USE_ITALICS_EXTRA,useItalics); intent.putExtra(USE_COLOR_EXTRA,color); and I could retrieve their values in the new activity like this: String msgString = intent.getStringExtra(MainActivity.MESSAGE_EXTRA); boolean useItalics = intent.getBooleanExtra(MainActivity.USE_ITALICS_EXTRA, false); int color = intent.getIntExtra(MainActivity.USE_COLOR_EXTRA,Color.BLACK); Using this technique the compiler will let you know if the constant names don’t match. And if you’ve misspelled one of the Strings, it doesn’t really matter, since both activities will use the same misspelling.

Sta Startin rtin rtingg Ext Extern ern ernal al A Activit ctivit ctivitie ie iess In the previous example, we used an Intent to move from one activity in our application to another activity within the same application. Our Intent constructor included the class of the activity which we wanted to startup. This kind of Intent is called an Explicit Intent. We can also use Intents to initiate an activity in a different application. In this case we pass in a String to tell Android what sort of activity we want started up, but we don’t actually provide the specific activity class. This is called an Implicit Intent. String constants for many activities are pre-defined. The String constant AlarmClock.ACTION_SET_ALARM can be used by your application to set an alarm. MediaStore.ACTION_IMAGE_CAPTURE starts up the camera application. Some pre-defined strings can be used for multiple purposes. Intent.ACTION_VIEW can be used to view a webpage, open the map app, or show a contact, all depending on the extra information provided. You can find detailed information on many of the Implicit Intents available on the “Common Intents” webpage here: https://developer.android.com/guide/components/intents-common.html There is also a list of intents up near the top of the Intent class documentation webpage here: https://developer.android.com/reference/android/content/Intent.html Implicit Intents will typical require you to specify a URI (Uniform Resource Identifier) providing the new activity with the data that it will need to operate on, and in some cases may require additional information passed through the use of the putExtra method we used previously in this handout. You can see the official URI specification here, although in most cases the Android documentation on Common Intents, linked a few paragraphs above, will give you all the information you need to know in order to use the given action: http://www.faqs.org/rfcs/rfc2396.html URI is the name of the official specification, which allows us to identify various resources as a string. For example, URLs are a subset of the URI specification and therefore: "http://www.stanford.edu/" is a URI which identifies a specific location on the web. URIs also provide a way of specifying a geographic location like this: "geo:37.43,-122.17" This specifies the location 37.43° N, 122.17° W, which is Stanford’s latitude and longitude. Unfortunately, we can’t simply use these strings for our intents. Instead Android provides an explicit Uri class. In an attempt to disambiguate these concepts, I will refer to the strings following the official Uniform Resource Identifier specification using all caps “URI”. I will refer to the Android objects using the name of the class, which has only the letter ‘U’ capitalized: “Uri”.

We’ll convert our URI strings to objects of Android’s Uri class. The Uri class provides a number of different static methods which can be used to generate Uri objects. The simplest one to use is Uri’s static parse method which takes a URI string and returns a Uri object like this: Uri webUrl = Uri.parse("http://www.stanford.edu/");

Some Basic Implicit Intent Examples With all that under our belt, let’s take a look at a few simple examples.

Opening the Web Browser Our application can open the web browser by using the generic ACTION_VIEW, which is a string constant found on the Intent class. To open a webpage, we first construct an Android Uri object corresponding to the web URI we want to open. We then create our intent, and set its data to our Uri object. Here’s a button click event handler which will open Android’s web application and direct it to Stanford’s homepage: public void onWeb(View view) { Uri webUrl = Uri.parse("http://www.stanford.edu/"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(webUrl); startActivity(intent); }

Opening the Map App To open a Map, we first construct a URI object for the latitude and longitude of the location we want to open. The rest of the code is exactly the same as what we just used for opening the web browser. Here’s a button click event handler which will open the Map application and focus it on Stanford: public void onMap(View view) { Uri geoUri = Uri.parse("geo:37.43,-122.17"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(geoUri); startActivity(intent); }

Checking for Resolving Activity What happens if our app tries to make a phone call and it turns out our app is running on a tablet which doesn’t have cell capabilities? In general, before starting an implicit intent you should check and make sure that there actually is an activity which can carry out our task. We do that with the resolveActivity method. Here’s an example which checks before trying to dial a phone call: public void onPhone(View view) { Uri telUri = Uri.parse("tel:(650) 555-0123"); Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(telUri); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent);

} }

Setting Permissions Some Implicit Intents require you to set permissions on your application. For example, if we want our application to be able to be able to set an alarm, we need to add the following line to our manifest.xml file:

Remember the manifest.xml file can be found in the first folder in the “Android Project View”:

This element should be a child of the itself, you can place it up at the top like this:





Adding Additional Data Some actions will require additional information to carry out their task. The can be done with the putExtra method. For example, to set an alarm, we use the AlarmClock.ACTION_SET_ALARM. We then add the timer length and a message. public void onTimer(View view) { Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER); intent.putExtra(AlarmClock.EXTRA_LENGTH,5); intent.putExtra(AlarmClock.EXTRA_MESSAGE,"Wake Up!!!"); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }

Han Handli dli dling ng Ot Other her App Appss Im Impl pl plicit icit IInt nt nten en ents ts We can setup our application to handle an Implicit Intent sent by another application by modifying its manifest.xml file. Each of the activities in your application should have their own tag in the manifest.xml file. The main activity’s tag will include an tag looking something like this:



Secondary activities will have simpler tags with no contained within them. To setup your application to respond to an activity, simply add an to whichever one of your activities you wish to handle the Implicit Intent. Here’s an example of an I added to handle a new action type which I defined myself:







In this particular case I wanted my main activity to respond to the new action, as well as continue on as the main activity for the application (the one that displays when the user clicks on the icon on the desktop), so my tag now has two different intent-filters. If I want to use this Implicit Intent in a different application, I will trigger it using code like this: Intent intent = new Intent("edu.stanford.cs108.STANFORD"); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } When this code is executed, the system will go through all the apps currently installed on the device, looking for those whose manifests say they can respond to the edu.stanford.cs108.STANFORD action. When my application is found to have that particular action string in its manifest, it will get started up and my activity will be displayed....


Similar Free PDFs