Wednesday, December 31



Through the use of a devious little prank application, you’ve explored how
intents, intent receivers, services, and activities work together in an
advanced, mostly background, application. i’ll now go over, step by step,
what you did and how you accomplished it.
getting it done
you did the following:
1.   you used an intent receiver with the  right permissions and a system-level
sms intent to arrange for your pranksmsreciever object to be
instantiated each time an sms arrives on  the phone. if your intent receiver
detected a very specific sms payloa d, it would respond by sending an
intent that would start your activity.
2.   this activity, named prankactivity , would listen for the specific intent
action sent by the pranksmsreceiver. when it received that precise
intent action, your activity would  display a “gotcha” message to the
victim. at the same time, the activity  would send out an intent meant to
start up a service. if, at any point the victim/user pressed a key on the
phone, the application would exit,  and the music service would be
terminated.
3.   the service class, called  prankservice, listening for the
prankactivity ’s intent, would start and begin to play an obnoxious,
predefined audio file. it  would continue to play until it was told to stop by
the  prankactivity ’s call to the method  stopservice.
34      android essentials
note  this sample application does not deal with the handset’s native
sms application. because all intent receivers are notified of an incoming
intent, your application will be competing for user attention with android’s
sms inbox application. in production, this may require a substantial timer
and perhaps a trigger text payload, which is a little more subtle than
“0xbadcat0_fire_the_missiles!”
further deviousness
here are a few ways you can explore and extend the prank
application on your own:
   get more evil by taking the activity out of the loop. launch the
prankservice directly from the intent receiver. do not give the
victim a way of shutting off the music.
   add a different text payload to  stop the music. this exercise
would be an excellent one to combine with the previous one.
   customize your “get even” message. create a prefix that triggers
the service and a payload, which is displayed by the main app
activity. pass this payload from the intent receiver to the activity
using a payload within the intent.  taunting, sometimes, needs fine-tuning.
these are just a few ways you can better learn the pieces of android
while at the same time making life miserable for those around you.
moving data in android
finally, to round your knowledge about  android’s application building
blocks, you need to focus on the content resolver. android does not give
the sdk particular access to the phones filesystem, as brew does. nor does
it offer a  recordstore , as does java me. your primary method for
passing data between your activities, intent receivers, and services is going
to be through the contentresolver  superclass. though y ou can store data
through files, preferences, and other da tabases, content re solvers can take
  android essentials       35
many forms, and android ships with  a few important content resolvers
built in. here’s a list, at time of publication, of the major android content
resolvers you’ll probably want to  interact with on a regular basis:
ƒ  browser
ƒ  bookmarks
ƒ  search history
ƒ  phone calls
ƒ  call log
ƒ  recent calls
ƒ  contacts
ƒ  system settings
ƒ  hardware settings (bluetooth, networking settings)
ƒ  software settings
android’s documentation gives an excellent walk-through of using the
contacts content resolver here:  http://code.google.com/android/
devel/data/contentproviders.html#usingacp.
quickly, i’ll walk you through adding a bookmark to the phone browser’s
bookmark list. first, you’ll want to sear ch the current list of bookmarks to
see whether your link is in place. second, you’ll add your bookmark if it
isn’t there.
note  it is possible to create your own content providers as a way to
wrap android’s sqlite implementation for universal access. you’ll get into
how to do this in later chapters. for  now you’re just going to handle the
“client” side of this content resolver interaction.
36      android essentials
android uses a custom implementation of sqlite to store information
locally. if you’re not familiar with the  basics of sql, now might be a good
time to brush up. i’m going to assume,  for the sake of expediency, that you
understand basic sql searching commands. if you need to brush up,
apress has an excellent resource at http://apress.com/book/
catalog?category=145 .
shameless self-promotion
let’s say in the “about” section of your application that you want to have a
button that adds your commercial so ftware page to the user’s web
bookmarks. you want to make sure it isn’t added twice if your user has
clicked the button again by accident. for the sake of this simple
demonstration, you’ll trigger this event in your sample application when
the user presses a key.
note  on an amusing note, if you need proof, as a developer, that
android is still not quite fully baked, you need look no further than the
documentation for  android.content.contentresolver under the
method getdatafilepath,  which states “do not use this function!!
someone added this, and they shouldn't have. you do not have direct
access to files inside of a content provider. don't touch this. go away.” it’s
good to know that even the technical writers for android’s documentation
have a sense of humor.
fetching the user’s bookmarks
it should be obvious, at least at this point, that a developer could do some
fairly nefarious things with access to  a user’s bookmarks. it’s not clear, at
this point, what android will do to keep this sort of thing from happening. i
suppose it’s up to the carriers to lock down or monitor this behavior. in any
case, you’ll use a call to the method  managedquery, which will return a list
of the user’s bookmarks:
  android essentials       37
cursor bookmarks =
    android.provider.browser.getallbookmarks
    (getcontentresolver());
int urlcolumn = bookmarks.getcolumnindex(
android.provider.browser.bookmarkcolumns. url );
cursor results;
string[] proj =  new  string[]
    {
        android.provider.basecolumns._id,
        android.provider.browser.bookmarkcolumns.url,
        android.provider.browser.bookmarkcolumns.title
    };
results =
    managedquery(android.provider.browser.bookmarks_uri,
     proj,  null,
    android.provider.browser.bookmarkcolumns.url
    + " asc");
i’ll now break down what’s happening. y ou’ll first get the column index of
the bookmark url. again, because androi d provides access to most of its
internal data in a sql format, you sh ould get used to referring to your
saved information in a database-centric  way. next you’ll set up the cursor,
an object similar to a java me recordstore  enumerator and set up your
projection string array. because you’re interested only in the columns
containing the url, you can keep  it very simple. the method call
managedquery is the call that will return  your data. you’ll pass in the uri
string for the bookmarks store, hand it  your simple projection array, leave
the  where  section empty, and tell it to sort  the urls in descending order.
Categories:

0 comments:

Post a Comment