merged-final.pdf
Document Details
Uploaded by FreedFlute
Tags
Full Transcript
ListView (link) An ordered collection of selectable choices key attributes in XML: android:clickable="bool" set to false to disable the list android:id="@+id/theID" unique ID for use in Java code android:entries="@array/array" set of opti...
ListView (link) An ordered collection of selectable choices key attributes in XML: android:clickable="bool" set to false to disable the list android:id="@+id/theID" unique ID for use in Java code android:entries="@array/array" set of options to appear in the list (must match an array in strings.xml) Static lists static list: Content is fixed and known before the app runs. – Declare the list elements in the strings.xml resource file. Android iPhone... Max OS X Dynamic lists dynamic list: Content is read or generated as the program runs. – Comes from a data file, or from the internet, etc. – Must be set in the Java code. – Suppose we have the following file and want to make a list from it: // res/raw/oses.txt Android iPhone... Max OS X List adapters adapter: Helps turn list data into list view items. – common adapters: ArrayAdapter, CursorAdapter Syntax for creating an adapter: ArrayAdapter name = new ArrayAdapter(activity, layout, array); the activity is usually this the default layout for lists is android.R.layout.simple_list_item_1 get the array by reading your file or data source of choice (it can be an array like String[], or a list like ArrayList) – Once you have an adapter, you can attach it to your list by calling the setAdapter method of the ListView object in the Java code. List adapter example ArrayList myArray =...; // load data from file ArrayAdapter adapter = new ArrayAdapter( this, android.R.layout.simple_list_item_1, myArray); ListView list = (ListView) findViewById(R.id.mylist); list.setAdapter(myAdapter); Handling list events Unfortunately lists don't use a simple onClick event. – Several fancier GUI widgets use other kinds of events. – The event listeners must be attached in the Java code, not in the XML. – Understanding how to attach these event listeners requires the use of Java anonymous inner classes. anonymous inner class: A shorthand syntax for declaring a small class without giving it an explicit name. – The class can be made to extend a given super class or implement a given interface. – Typically the class is declared and a single object of it is constructed and used all at once. Attaching event listener in Java // MainActivity.java public void mybuttonOnClick() {... } Button button = (Button) findViewById(R.id.mybutton); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // code to run when the button gets clicked } }); // this was the required style for event listeners // in older versions of Android :-/ List events List views respond to the following events: – setOnItemClickListener(AdapterView.OnItemClickListener) Listener for when an item in the list has been clicked. – setOnItemLongClickListener(AdapterView.OnItemLongClickListener) Listener for when an item in the list has been clicked and held. – setOnItemSelectedListener(AdapterView.OnItemSelectedListener) Listener for when an item in the list has been selected. Others: – onDrag, onFocusChanged, onHover, onKey, onScroll, onTouch,... List event listener example ListView list = (ListView) findViewById(R.id.id); list.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView list, View row, int index, long rowID) { // code to run when user clicks that item... } } ); CS371m - Mobile Computing Anatomy of an Android App and the App Lifecycle Application Components four primary components (plus one) different purposes and different lifecycles Activity – single screen with a user interface, app may have several activities, subclass of Activity – Most of early examples will be activities Service – Application component that performs long- running operations in background with no UI – example, an application that automatically responds to texts when driving Application Components Content Providers – a bridge between applications to share data – for example the devices contacts information – we tend to use these, but not create new ones Broadcast Receivers – component that responds to system wide announcements – battery low, screen off, date changed – also possible to initiate broadcasts from within an application Intents – used to pass information between applications Activity Stack Most recently User currently interacting with me created is at Top Activity 1 Pressing Back or destroying A1 Activity 2 will bring me to the top Activity 3 If Activities above me use too Activity N many resources, I’ll be destroyed! Beware having multiple instance of the same activity on the stack Typical Game High Scores Activity Splash Screen Main Menu Game Play Activity Activity Activity Settings Activity Conder & Darcey (2010), Fig 4.1, p. 74 5 Activity Lifecycle http://developer.android.com/reference/android/app/Activity.html Starting Activities Android applications don't start with a call to main(String[]) instead a series of callback methods are invoked by the Android OS each corresponds to specific stage of the Activity / application lifecycle callback methods also used to tear down Activity / application Simplified Lifecycle Diagram ready to interact with user Understanding the Lifecycle Necessary to overload callback methods so your app behaves well: App should not crash if the user receives a phone call or switches to another app while using your app. App should not consume valuable system resources when the user is not actively using it. App should not lose the user's progress if they leave your app and return to it at a later time. App should not crash or lose the user's progress when the screen rotates between landscape and portrait orientation. http://developer.android.com/training/basics/activity-lifecycle/starting.html Primary States Active – activity is in the foreground and user can interact with it Paused – activity partially obscured by another activity and user cannot interact with it (for example when working with a menu or dialog) Stopped – activity completely hidden and not visible to user. It is in the background. – Activity instance and variables are retained but no code is being executed by the activity Dead, activity terminated (or never started) Two other states, Created and Started, but they are transitory onCreate -> onStart -> onResume Clicker What happens if your app starts an Activity that is not declared in the manifest? A. activity starts B. dialog asks user if they want to allow Activity C. nothing, a no-op D. compile error E. runtime error AndroidManifest.xml All Activities that are part of application must be registered in Manifest Specify Activity to start with 12 Purpose of Lifecycle Phases Entire lifetime: onCreate / onDestroy – Load UI – Could start and stop threads that should always be running Visible lifetime: onStart / onStop – Access or release resources that influence UI – write info to files if necessary Foreground lifetime: onResume / onPause – Restore state and save state – Start and stop audio, video, animations Activity Lifecycle App overload these methods from Activity: – onCreate(), onStart(), onResume(), onPause(), onStop(), onRestart(), onDestroy() – Use the Log class to log activity – methods: v, d, i, w, e – VERBOSE, DEBUG, INFO, WARN, ERROR – Create a TAG so we can filter Note, must always call parents method we are overriding first. Anti pattern? onCreate Documentation LifeCycleTest Run the app and open the Logcat view. – Android Studio -> Android button at bottom -> logcat Activity Lifecycle App examine Logcat try starting other apps and opening dialog what happens if we rotate device? app's activities not fixed in portrait mode Logcat After app started Logcat Rotate device Pausing - onPause method when activity paused you should – stop animations of other CPU intensive tasks – release resources such as broadcast receivers (app stops listening for broadcast info) and handles to sensors such as GPS device or handles to the camera – stop audio and video if appropriate Stopping - onStop() Many scenarios cause activity to be stopped Well behaved apps save progress and restart seamlessly Activity stopped when: – user performs action in activity that starts another activity in the application – user opens Recent Apps window and starts a new application – user receives phone call use onStop to release all resources and save information (persistence) How to stop an Activity yourself? Generally, don't worry about it! "Note: In most cases, you should not explicitly finish an activity using these methods. As discussed in the following section about the activity lifecycle, the Android system manages the life of an activity for you, so you do not need to finish your own activities. Calling these methods could adversely affect the expected user experience and should only be used when you absolutely do not want the user to return to this instance of the activity." methods: finish(), finishActivity() Saving State activities that are paused or stopped the state of the activity (instance vars) are retained – even if not in foreground When activity destroyed the Activity object is destroyed – can save information via onSaveInstanceState method. Write data to Bundle, Bundle given back when restarted Activity Destruction app may be destroyed under normal circumstances – on its own by calling finish or user pressing the back button to navigate away from app – normal lifecycle methods handle this onPause() -> onStop() -> onDestroy If the system must destroy the activity (to recover resources or on an orientation change) must be able to recreate Activity Activity Destruction Activity Destruction If Activity destroyed with potential to be recreate later system calls the onSaveInstanceState (Bundle outState) method Bundle is a data structure a map – String keys – put methods for primitives, arrays, Strings, Serializables (Java), and Parcels (android) onSaveInstanceState onRestoreInstanceState() systems write info about views to Bundle other information must be added by programmer – example, board state for mastermind When Activity recreated Bundle sent to onCreate and onRestoreInstanceState() use either method to restore state data / instance variables Activity Lifecycle App How do we keep the onPauseCounter from getting reset to 0 when app is rotated? Write value to bundle in onSaveInstanceState override onRestoreInstanceState saving and restoring state Starting You Own Activities You will often start new Activities within your Activity – accomplish a task – get some data Click Button to get name – on button click (look at xml) – create an intent – call startActivityForResult – override onActivityResult() – add new Activity to Manifest – add data to intent, setResult, finish http://developer.android.com/guide/topics/fundamentals/activities.html#StartingAnActivity Intent Demo Intent holding constant startActivityForResult() LifeCycle Name TestActivity Intent holding Getter Name setResult() 31 Playing Well (or not) With Others The Play Sound button causes a MediaPlayer to be created and plays a sound The Lifecycle app does not clean up after itself If app destroyed MediaPlayer keeps playing!! References http://developer.android.com/guide/componen ts/activities.html Android Introduction by Marko Gargenta, http://www.lecturemaker.com/2009/10/androi d-software-platform/ Android Dev Guide http://developer.android.com/guide/topics/fun damentals.html http://developer.android.com/guide/topics/fun damentals/activities.html Pro Android by Hashimi & Komatineni (2009) Frank McCown, Harding University Drawing 2D graphics To draw our own custom 2D graphics on screen, we'll make a custom View subclass with the drawing code. If the app is animated (such as a game), we'll also use a thread to periodically update the graphics and redraw them. Custom View template public class ClassName extends View { // required constructor public ClassName(Context context, AttributeSet attrs) { super(context, attrs); } // this method draws on the view @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawing code; } } // recall: y-axis increases downward! Using your custom view You can insert your custom view into an activity's layout XML: Canvas object methods (link) c.drawARGB(alpha, r, g, b); - fill window with color (rgb=0-255) c.drawArc(...); - draw a partial ellipse c.drawBitmap(bmp, x, y, null); - draw an image c.drawCircle(centerX, centerY, r, paint); - draw a circle c.drawLine(x1, y1, x2, y2, paint); - draw a line segment c.drawOval(x1, y1, x2, y2, paint); * (requires Android 5.0) c.drawOval(new RectF(x1, y1, x2, y2), paint); - draw oval/circle c.drawPoint(x, y, paint); - color a single pixel c.drawRect(x1, y1, x2, y2, paint); * (requires Android 5.0) c.drawRect(new RectF(x1, y1, x2, y2), paint); - draw rectangle c.drawRoundRect(x1, y1, x2, y2, rx, ry, paint); * (requires Android 5.0) c.drawRoundRect(new RectF(x1, y1, x2, y2), rx, ry, paint); c.drawText("str", x, y, paint); - draw a text string c.getWidth(), c.getHeight() - get dimensions of drawing area Paint (link) Many methods accept a Paint, a color to use for drawing. – Create a Paint by specifying an alpha (opacity) value, and red/green/blue (RGB) integer values, from 0 (none) to 255 (full). Paint name = new Paint(); name.setARGB(alpha, red, green, blue); // example Paint purple = new Paint(); purple.setARGB(255, 255, 0, 255); purple.setStyle(Style.FILL_AND_STROKE); // FILL, STROKE – Paint has other useful methods like: getTextBounds, measureText, setAlpha, setAntiAlias, setStrokeWidth, setStyle, setTextAlign, setTextSize, setTypeface Typeface (link) In Android, a font is called a Typeface. Set a font inside a Paint. You can create a Typeface based on a specific font name: Typeface.create("font name", Typeface.STYLE) styles: NORMAL, BOLD, ITALIC, BOLD_ITALIC Or based on a general "font family": Typeface.create(Typeface.FAMILY_NAME, Typeface.STYLE) family names: DEFAULT, MONOSPACE, SERIF, SANS_SERIF Or from a file in your src/main/assets/ directory: Typeface.createFromAsset(getAssets(), "filename") // example: use a 40-point monospaced blue font Paint p = new Paint(); p.setTypeface( Typeface.create(Typeface.MONOSPACE, Typeface.BOLD)); p.setTextSize(40); p.setARGB(255, 0, 0, 255); Bitmap images (link) Draw an image (such as.png or.jpg) using the Bitmap class. Bitmap name = BitmapFactory.decodeResource( getResources(), R.drawable.ID); // example: draw heart.png on screen at (0, 0) Bitmap bmp = BitmapFactory.decodeResource( getResources(), R.drawable.heart); canvas.drawBitmap(bmp, 0, 0, null); // you can also read a Bitmap from an input stream URL url = new URL("http://example.com/myImage.jpg"); Bitmap bmp = BitmapFactory.decodeStream( url.openStream()); Target exercise Write an app whose main activity displays a custom view that draws a "target" figure. – The outer red circle fills 100% of the main view's width and height. – There are 5 total circles, all centered; 3 red, 2 white. – Each circle is 20% smaller than the last: the first (red) is 100% of the window size, the second (white) is 80% of the window size, the third (red) is 60% of the window size, the fourth (white) is 40% of the window size, the fifth (white) is 20% of the window size. (Challenge: Can you introduce a constant so that the number of ovals is easy to change?) Target solution public class TargetView extends View { public TargetView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint red = new Paint(); red.setARGB(255, 255, 0, 0); Paint white = new Paint(); white.setARGB(255, 255, 255, 255); int w = canvas.getWidth(), h = canvas.getHeight(); for (int i = 0; i < 5; i++) { canvas.drawOval(new RectF( w*i/10, h*i/10, w*(10-i)/10, h*(10-i)/10), i % 2 == 0 ? red : white); } } } Animation via redrawing To animate a view, you must redraw it at regular intervals. – On each redraw, change variables/positions of shapes. Force a view to redraw itself by calling its invalidate method. – But you can't just do this in a loop; this will lock up the app's UI and lead to poor performance. Threads thread: A "lightweight process"; a single sequential flow of execution or isolated sub-task within one program. – A means to implement programs that seem to perform multiple tasks simultaneously (a.k.a. concurrency). – Threads within the same process share data with each other. i.e., Variables created in one thread can be seen by others. "shared-memory concurrency" – sometimes called a lightweight process Using a Thread You can create a Thread by passing it a Runnable object with a run() method containing the code to execute. – other Thread methods: start, stop, sleep, isRunning, join Thread thread = new Thread(new Runnable() { public void run() { // code to execute in thread goes here } }); thread.start(); Redrawing a View in a Thread Because of Android quirks, you can't just create a Thread and then call invalidate on your View from that thread. – Instead, you must use a "Handler" object to make the call, which requires its own second Runnable to do so. (blargh!) // repaint the view a single time, in another thread Thread thread = new Thread(new Runnable() { public void run() { Handler h = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { public void run() { myView.invalidate(); } }); } }); thread.start(); Bouncing ball exercise Write an app that draws a bouncing red ball. The ball moves in the x/y dimensions and bounces back when it hits any edge of the screen. – background color: yellow – ball color: red – ball size: 100 x 100px – ball velocity: < 80px per in x/y direction (random) – ball should update 50 times per second Mouse touch events (link) To handle finger presses from the user, write an onTouchEvent method in your custom View class. – actions: ACTION_DOWN, ACTION_UP, ACTION_MOVE,... @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); if (event.getAction() == MotionEvent.ACTION_DOWN) { // code to run when finger is pressed } return super.onTouchEvent(event); } Keyboard events (link) If you want to handle key presses (if the device has a keyboard): set your app to receive keyboard "focus" in View constructor: requestFocus(); setFocusableInTouchMode(true); write onKeyDown/Up methods in your custom View class. – each key has a "code" such as KeyEvent.KEYCODE_ENTER @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_X) { // code to run when user presses the X key } return super.onKeyDown(keyCode, event); } A Sprite class sprite: An object of interest in a game. – possible data: location, size, velocity, shape/image, points,... – Many games declare some kind of Sprite class to represent the sprites. // an example sprite class public class Sprite { RectF rect; float dx, dy; Paint paint;... } Collision detection collision detection: Determining whether sprites in the game world are touching each other (and reacting accordingly). Android's RectF (link) and other shapes have methods to check whether they touch: – rect1.contains(x, y) – rect1.contains(rect2) – RectF.intersects(rect1, rect2) Harder to compute for non-rectangular sprites. Some games use a smaller collision rectangle to give the collisions a bit of slack. WakeLock To prevent screen from blanking, use a wake lock. in AndroidManifest.xml: in app's activity Java code: // create the lock (probably in onCreate) PowerManager pwr = (PowerManager) getSystemService(POWER_SERVICE); WakeLock lock = pwr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "my lock"); // turn on the lock (in onResume) lock.acquire(); // turn off the lock (in onPause) lock.release(); Full screen mode To put an app (e.g. a game) into full screen mode, which hides the notifications and status bar, put the following in your activity's onCreate method: requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); Creating the Example Project in Android Studio Adding Views to an Activity The onCreate() method is currently designed to use a resource layout file for the user interface. Begin, therefore, by deleting this line from the method: The next modification to the onCreate() method is to write some Java code to add a RelativeLayout object with a single Button view child to the activity. Setting View Properties Set the background of the RelativeLayout view to be blue and the Button view to display text that reads “Press Me”. Adding Layout Parameters and Rules In order to instruct the layout view to place the button in a different location, in this case centered both horizontally and vertically, it will be necessary to create a LayoutParams object and initialize it with the appropriate values. The next step is to add some additional rules to the parameters to instruct the layout parent to center the button vertically and horizontally. Last step, need to pass the LayoutParams object through as an argument when the child view is added to the parent. or: Complete code Output Files and storage Android can read/write files from two locations: – internal and external storage. – Both are persistent storage; data remains after power-off / reboot. internal storage: Built into the device. – guaranteed to be present – typically smaller (~1-4 gb) – can't be expanded or removed – specific and private to each app – wiped out when the app is uninstalled File (link) and Streams (link) java.io.File - Objects that represent a file or directory. – methods: canRead, canWrite, create, delete, exists, getName, getParent, getPath, isFile, isDirectory, lastModified, length, listFiles, mkdir, mkdirs, renameTo java.io.InputStream, OutputStream - Stream objects represent flows of data bytes from/to a source or destination. – Could come from a file, network, database, memory,... – Normally not directly used; they only include low-level methods for reading/writing a byte (character) at a time from the input. – Instead, a stream is often passed as parameter to other objects like java.util.Scanner, java.io.BufferedReader, java.io.PrintStream to do the actual reading / writing. Using internal storage (link) An activity has methods you can call to read/write files: – getFilesDir() - returns internal directory for your app – getCacheDir() - returns a "temp" directory for scrap files – getResources().openRawResource(R.raw.id) - read an input file from res/raw/ – openFileInput("name", mode) - opens a file for reading – openFileOutput("name", mode) - opens a file for writing You can use these to read/write files on the device. – many methods return standard java.io.File objects – some return java.io.InputStream or OutputStream objects, which can be used with standard classes like Scanner, BufferedReader, and PrintStream to read/write files (see Java API) Internal storage example 1 // read a file, and put its contents into a TextView // (assumes hello.txt file exists in res/raw/ directory) Scanner scan = new Scanner( getResources().openRawResource(R.raw.hello)); String allText = ""; // read entire file while (scan.hasNextLine()) { String line = scan.nextLine(); allText += line; } myTextView.setText(allText); scan.close(); Internal storage example 2 // write a short text file to the internal storage PrintStream output = new PrintStream openFileOutput("out.txt", MODE_PRIVATE)); output.println("Hello, world!"); output.println("How are you?"); output.close();... // read the same file, and put its contents into a TextView Scanner scan = new Scanner( openFileInput("out.txt", MODE_PRIVATE)); String allText = ""; // read entire file while (scan.hasNextLine()) { String line = scan.nextLine(); allText += line; } myTextView.setText(allText); scan.close(); External storage external storage: Card that is inserted into the device. (such as a MicroSD card) – can be much larger than internal storage (~8-32 gb) – can be removed or transferred to another device if needed – may not be present, depending on the device – read/writable by other apps and users; not private to your app – not wiped when the app is uninstalled, except in certain cases External storage permission If your app needs to read/write the device's external storage, you must explicitly request permission to do so in your app's AndroidManifest.xml file. – On install, the user will be prompted to confirm your app permissions.... Using external storage Methods to read/write external storage: – getExternalFilesDir("name") - returns "private" external directory for your app with the given name – Environment.getExternalStoragePublicDirectory(name) - returns public directory for common files like photos, music, etc. pass constants for name such as Environment.DIRECTORY_ALARMS, DIRECTORY_DCIM, DIRECTORY_DOWNLOADS, DIRECTORY_MOVIES, DIRECTORY_MUSIC, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES You can use these to read/write files on the external storage. – the above methods return standard java.io.File objects – these can be used with standard classes like Scanner, BufferedReader, and PrintStream to read/write files (see Java API) External storage example // write short data to app-specific external storage File outDir = getExternalFilesDir(null); // root dir File outFile = new File(outDir, "example.txt"); PrintStream output = new PrintStream(outFile); output.println("Hello, world!"); output.close(); // read list of pictures in external storage File picsDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); for (File file : picsDir.listFiles()) {... } Checking if storage is available public boolean isExternalStorageWritable() { return Environment.MEDIA_MOUNTED.equals( Environment.getExternalStorageState()); } public boolean isExternalStorageReadable() { return isExternalStorageWritable() || Environment.MEDIA_MOUNTED_READ_ONLY.equals( Environment.getExternalStorageState()); } Accessing web data (link) To read data from the web, first request the INTERNET permission in your AndroidManifest.xml: Then you can use the standard java.net.URL class to connect to a file or page at a given URL and read its data: URL url = new URL("http://foobar.com/example.txt"); Scanner scan = new Scanner(url.openStream()); while (scan.hasNextLine()) { String line = scan.nextLine();... } Playing sound effects (link) Find sound files such as.WAV,.MP3 put sound files in project folder app/src/main/res/raw in Java code, refer to audio file as R.raw.filename – (don't include the extension; R.raw.foo for foo.mp3) – use simple file names with only letters and numbers Load and play clips using Android's MediaPlayer class MediaPlayer mp = MediaPlayer.create(this, R.raw.filename); mp.start(); – other methods: stop, pause, isLooping, isPlaying, getCurrentPosition, release, seekTo, setDataSource, setLooping Multiple Activities Many apps have multiple activities. – Example: In an address book app, the main activity is a list of contacts, and clicking on a contact goes to another activity for viewing details. – An activity A can launch another activity B in response to an event. – The activity A can pass data to B. – The second activity B can send data back to A when it is done. Adding an Activity in Android Studio, right click "app" at left: New -> Activity – creates a new.XML file in res/layouts – creates a new.java class in src/java – adds information to AndroidManifest.xml about the activity (without this information, the app will not allow the activity) Activities in Manifest Every activity has an entry in project's AndroidManifest.xml, added automatically by Android Studio: Intents intent: a bridge between activities; a way for one activity to invoke another – the activity can be in the same app or in a different app – can store extra data to pass as "parameters" to that activity – second activity can "return" information back to the caller if needed Creating an Intent To launch another activity (usually in response to an event), create an Intent object and call startActivity with it: Intent intent = new Intent(this, ActivityName.class); startActivity(intent); If you need to pass any parameters or data to the second activity, call putExtra on the intent. – It stores "extra" data as key/value pairs, not unlike a Map. Intent intent = new Intent(this, ActivityName.class); intent.putExtra("name", value); intent.putExtra("name", value); startActivity(intent); Extracting extra data In the second activity that was invoked, you can grab any extra data that was passed to it by the calling act. – You can access the Intent that spawned you by calling getIntent. – The Intent has methods like getExtra, getIntExtra, getStringExtra, etc. to extract any data that was stored inside the intent. public class SecondActivity extends Activity {... public void onCreate(Bundle savedState) { super.onCreate(savedState); setContentView(R.layout.activity_second); Intent intent = getIntent(); String extra = intent.getExtra("name");... } } Waiting for a result If calling activity wants to wait for a result from called activity: – Call startActivityForResult rather than startActivity. startActivityForResult requires you to pass a unique ID number to represent the action being performed. By convention, you declare a final int constant with a value of your choice. The call to startActivityForResult will not wait; it will return immediately. – Write an onActivityResult method that will be called when the second activity is done. Check for your unique ID as was passed to startActivityForResult. If you see your unique ID, you can ask the intent for any extra data. – Modify the called activity to send a result back. Use its setResult and finish methods to end the called activity. Sending back a result In the second activity that was invoked, send data back: – Need to create an Intent to go back. – Store any extra data in that intent; call setResult and finish. public class SecondActivity extends Activity {... public void myOnClick(View view) { Intent intent = new Intent(); intent.putExtra("name", value); setResult(RESULT_OK, intent); finish(); // calls onDestroy } } Grabbing the result public class FirstActivity extends Activity { private static final int REQ_CODE = 123; // MUST be 0-65535 public void myOnClick(View view) { Intent intent = getIntent(this, SecondActivity.class); startActivityForResult(intent, REQ_CODE); } protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (requestCode == REQ_CODE) { // came back from SecondActivity String data = intent.getStringExtra("name"); Toast.makeText(this, "Got back: " + data, Toast.LENGTH_SHORT).show(); } } }