< CS193A Android Programming
Today a few random topics
Automatic Resource Selection 1 -- drawable
- (See previous MonkeyImage example)
- When activity gets an orientation change, gets a full kill cycle. In particular, this allows the resource loading to switch between -land and -port orientations
- Have "drawable/background.jpg" and "drawable-land/background.jpg"
- Code refers to R.drawable.background -- the system selects the right one.
- The -xxx selector goes on a directory, not a file
- The system is smart about piecing things together -- using "drawable" as a default, then layering on more specific bits from more specific -xxx folders.
- More complex cases: drawable-ldpi drawable-mdpi drawable-hdpi -- these refer to low-medium-high ranges of pixel density. Could have icons, art etc. with different sizes, ready to go for the various densities. This can be very fast.
- See http://developer.android.com/guide/topics/resources/providing-resources.html
Automatic Resource Selection 2 -- string
- (updated NetworkFetch Example)
- In values/strings.xml have "download" string with the value "Download" and app_name string -- these are the defaults:
<string name="app_name">NetworkFetch</string>
<string name="download">Download</string>
- Add "values-es" folder, contains strings.xml, containing one string:
<string name="download">Descargar</string>
- main.xml refers to @string/download as the button title -- that's all there is to it
- In emulator or on real phone, use Settings : Language to set the language to Spanish (es) .. see how starting the app now picks the right string for the button title
- Note how the English app_name is still used, but the system patches in the Download string when appropriate
- Google translate for quick n dirty translation. To do it properly, it's best to have a human to do it. http://translate.google.com/#auto|es|download
Dynamic Pixel Scale Independence
- When laying out your UI, use DIP (also known as DP) -- device independent pixels (160/inch)
- As previously: in main.xml express size of things in DP pixels
- The actual device has some size and some density
- Dynamically scale your image to be, say, 1 inch = 160 dp across regardless of the device density
- Make the image resource over-sized, so it gets scaled down
- Only need one image, but now have the CPU cost of doing the scaling, but it works for everything (the time/space tradeoffs here contrast with the -xxx way which avoids rescaling)
- Monkey code:
mMonkey = makeScaled(BitmapFactory.decodeResource(context.getResources(), R.drawable.monkey), 160 * mScale);
mAlternate = makeScaled(BitmapFactory.decodeResource(context.getResources(), R.drawable.alternate), 160 * mScale);
// Note: density scaling: here we choose to make the monkey 160 device-independent-pixels wide, exactly 1 inch.
// By multiplying by the passed in scale, the monkey will be the right number of actual pixels
// wide to be 1 inch for whatever the display density.
Foreground/Background Hierarchy
- Hierarchy of how things can "run":
- Activity in front, on the UI thread .. 90% of cases are here
- a. Slow computation ... use AsyncTask
- b. onPause() ... depends .. could kill the computation, or could leave it run despite not being in front
- c. activity is destroyed (say a rotation) or the computation is very long running. Could use a "Service". e.g. a long download or playing music. A service is not tied to the activity UI and indeed has no UI. (http://developer.android.com/guide/topics/fundamentals/services.html) I'm mentioning Services so you know they exist, but we are not doing them in detail.
- d. device goes to sleep, so your computation stops. If you need to keep the device running see "wakeLock" and "wifiLock".
- Related: the "AlarmManager" lets you schedule things to run at some interval, or when certain things happen
Notification Manager
- Ways to show the user something: in the activity UI, toast, notification
- Notifications appear at the top of the screen, and the user responds to each one when they can (do not require an immediate response)
- The notification item has an intent .. what to do when the user selects it
- e.g. notification for a text that arrived, selecting it shows the full text
- Can be created from, say, a background service
- Here is example code creating a notification for the network fetch, although this is not really an appropriate use, as NetworkFetch shows its status right in its own UI for the user.
/** Puts up a notification with the given text.
This is not really an appropriate UI for this app, but I wanted
to show the code for this case.
*/
public void makeNotification(CharSequence text) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Text here appears at the top of the screen at the moment of notification
int icon = android.R.drawable.ic_dialog_info;
// Above grabs a built in icon, but could make a custom one in our own R.drawable
long now = System.currentTimeMillis();
Notification notification = new Notification(icon, text, now);
// Make an intent to fire when the user selects the notification .. e.g.
// intent/activity to show the text message. Here we make a dummy intent
// that just starts our main activity.
Intent notificationIntent = new Intent(this, NetworkFetchActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// Text here appears in the body of the notification when the user
// pulls it down to look at it.
Context context = getApplicationContext();
CharSequence title = "Notification title";
CharSequence detailText = text;
notification.setLatestEventInfo(context, title, detailText, contentIntent);
// Put up the notification. You can give each notification its own
// id to support multiple pending ones. Here I just use 1.
int id = 1;
mNotificationManager.notify(id, notification);
}
Last homework! Due Fri Dec 9th, or ask Madiha for an extension. You have a choice of either a "game" project or a "AsyncTask" project.
1. Game: you may start with your "ducks" project or start a new one. Add gesture support. A user drag-gesture on a duck or some other on-screen thing should change its position/trajectory in some way that is up to you. Optional: implement the invalidate(rect) optimization.
2. AsyncTask: your app should have a Start button which starts up an AsyncTask that does something. The AsyncTask should update some status and/or progress bar periodically as it runs. Optional: one interesting application would be that the AsyncTask adds some text to a TextView or list, say, every 10 seconds. Program it to keep running, even after an onPause .. in this way, you can observe when the device goes through a real sleep/wake cycle vs. just blanking the screen.
In case you need it, "block" your AsyncTask to do nothing for a number of milliseconds, use this snippet:
try {
Thread.sleep(5000); // 5 seconds
}
catch (InterruptedException ignored) { }