Android App Components
Content Provider
Manages access to a central repository of data
Data sharing across multiple applications
Data Abstraction
Secure data access
Inter-process communication
Tables & Rows (conceptually like a database)
Independent of underlying data storage medium (e.g. database, files, shared
preferences, etc.)
API
ContentProvider
ContentResolver
Cursor and ContentValues
Uri and UriMatcher
Creating a Content Provider
Design data storage
Design content URIs
Authority
Path
Implement ContentProvider interface
onCreate
getType
query
insert
update
delete
Register in manifest and set any permissions required
Optionally provide a Contract class for specifying provider details
Using a Content Provider
Use ContentResolver
A remote proxy object for the provider
Provides same methods as provided by the provider
onCreate
getType
query
insert
update
delete
Standard Content Providers
Browser
Calendar
Contacts
CallLog
MediaStore
UserDictionary
Services
Application component without a UI
A long-running operation in the background
Continues running even if user switches to
another application
May be invoked remotely from a different
process through IPC
Example Usage Scenarios
Download / Upload / Synchronize data on network
Alarms / notifications / reminders (on some specific event)
Send emails / messages in a fail-safe manner
Play audio / music in the background
Archive data
Authenticate users
Other application specific scenarios
Example
public class NotesDataSyncService extends Service {
public void onCreate() {
}
public int onStartCommand(Intent intent,int flags,int startId){
[Link](this,"Service starting",Toast.LENGTH_SHORT).show();
return START_NOT_STICKY;
}
public IBinder onBind(Intent intent){
return null;
}
}
Service Types
Started
Performs a background operation and does not return any result
to the caller
Once started, may run indefinitely unless
explicitly stopped
killed by the system but may be restarted based upon restart behavior and
any pending requests
Useful for cases like syncing data, playing audio, etc.
Invocation
from other App components (Activities or BroadcastRecievers) using
explicit intents
Intent intent = new Intent(this,[Link]);
startService(intent);
calls onStartCommand
Service Types
Bound
Bound to the application component starting the service
Runs only as long as another component is bound to it
client-server communication
service acts as the server
Multiple components may bind to a service at once
Destroys when all bound components unbind
Useful for cases like authentication, play audio with
status updates, etc.
Invocation
Using Binder, ServiceConnection and bindService
calls onBind
public class NotesDataSyncService extends Service {
private final IBinder binder = new LocalBinder();
public void onCreate() {
}
public int onStartCommand(Intent intent,int flags,int startId){
[Link](this,"Service starting",Toast.LENGTH_SHORT).show();
return START_NOT_STICKY;
}
public IBinder onBind(Intent intent){
return binder;
}
public class LocalBinder extends Binder{
public NotesDataSyncService getService(){
return [Link];
}
}
public String getStatus(){
return "synchronization in progress";
}
}
public class NotesActivity extends BaseActivity
{
NotesDataSyncService dataService;
boolean bound = false;
...
private ServiceConnection connection = new ServiceConnection(){
public void onServiceConnected(ComponentName className, IBinder binder){
dataService = (([Link]) binder).getService();
bound = true;
}
};
showMessage([Link]());
public void onServiceDisconnected(ComponentName className){
bound = false;
}
protected void onStart(){
[Link]();
Intent intent = new Intent(this,[Link]);
bindService(intent,connection, Context.BIND_AUTO_CREATE);
}
protected void onStop(){
[Link]();
if(bound){
unbindService(connection);
}
}
}
Some Considerations
Service not a separate process
Service itself doesn't mean a new process
Runs in the same process of the application by default
It may be specified to run in a different process
Remote services require IPC mechanisms
Service not a thread
Service itself doesn't launch a new thread
Thread management needs to be done explicitly
Necessary to avoid application not responding errors
Broadcast Receivers
Broadcasts
system or custom-generated notifications for events
broadcasted to interested application components that
may need to take corresponding action
API
sendBroadcast: asynchronous operation to notify all receivers in
parallel
sendOrderedBroadcast: asynchronous operation to notify all
receivers in sequence may be aborted in between
Examples
[Link].BOOT_COMPLETED
[Link].BATTERY_LOW
Broadcast Receivers
Broadcast receiver
An event listener
Registered to receive broadcasted intents
Runs in background may send UI notifications
Invoke a service
Only start
Cannot bind
Example broadcast receiver registered statically in the manifest
public class ConnectivityReceiver extends BroadcastReceiver {
public void onReceive(Context context,Intent intent){
String message = "received";
[Link](context,message,Toast.LENGTH_SHORT).show();
}
}
<receiver android:name="ConnectivityReceiver">
<intent-filter>
<action android:name="[Link].CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Example broadcast receiver registered dynamically in an activity
public class NotesActivity extends BaseActivity
{
ConnectivityReceiver receiver;
public void onCreate(Bundle savedInstanceState)
{
IntentFilter intent = new
IntentFilter("[Link].CONNECTIVITY_CHANGE");
receiver = new ConnectivityReceiver();
registerReceiver(receiver,intent);
}
protected void onDestroy(){
unregisterReceiver(receiver);
[Link]();
}
}
Example broadcast receiver invoking a service
public class ConnectivityReceiver extends BroadcastReceiver {
public void onReceive(Context context,Intent intent){
String message = "received";
[Link](context,message,Toast.LENGTH_SHORT).show();
SharedPreferences preferences =
[Link]("service",Context.MODE_PRIVATE);
boolean started = [Link]("started",false);
[Link] editor = [Link]();
if(!started){
Intent serviceIntent = new Intent(context,[Link]);
[Link](serviceIntent);
[Link]("started",true);
}
else{
Intent serviceIntent = new Intent(context,[Link]);
[Link](serviceIntent);
[Link]("started",false);
}
[Link]();
}
}
SMS Example
SMS received broadcast
[Link].SMS_RECEIVED
Ordered broadcast may be aborted by some
application
Requires permissions
[Link].RECEIVE_SMS
[Link].READ_SMS
Intent structure
Generally carries an array of PDUs, mapped to string pdus
public class SmsReceiver extends BroadcastReceiver {
SmsManager sms = [Link]();
public void onReceive(Context context,Intent intent){
Bundle bundle = [Link]();
try {
if (bundle != null) {
Object[] pdusObj = (Object[]) [Link]("pdus");
for (int i = 0; i < [Link]; i++) {
SmsMessage currentMessage = [Link]((byte[]) pdusObj[i]);
String number = [Link]();
String message = [Link]();
String text = "senderNum: "+ number + ", message: " + message;
[Link](context, text , Toast.LENGTH_LONG).show();
}
}
} catch (Exception e) {
}
}
}
<manifest xmlns:android="[Link]
package="[Link]"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="[Link].RECEIVE_SMS" />
<uses-permission android:name="[Link].READ_SMS" />
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="SimpleMessenger"
android:label="@string/app_name">
<intent-filter>
<action android:name="[Link]" />
<category android:name="[Link]" />
</intent-filter>
</activity>
<receiver android:name="SmsReceiver">
<intent-filter>
<action android:name="[Link].SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>