You are on page 1of 23

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){
Toast.makeText(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,NotesDataSyncService.class);
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){
Toast.makeText(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 NotesDataSyncService.this;
}
}
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 = ((NotesDataSyncService.LocalBinder) binder).getService();
bound = true;
}

};

showMessage(dataService.getStatus());

public void onServiceDisconnected(ComponentName className){


bound = false;
}

protected void onStart(){


super.onStart();
Intent intent = new Intent(this,NotesDataSyncService.class);
bindService(intent,connection, Context.BIND_AUTO_CREATE);
}
protected void onStop(){
super.onStop();
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

android.intent.action.BOOT_COMPLETED
android.intent.action.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";
Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
}
}

<receiver android:name="ConnectivityReceiver">
<intent-filter>
<action android:name="android.net.conn.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("android.net.conn.CONNECTIVITY_CHANGE");
receiver = new ConnectivityReceiver();
registerReceiver(receiver,intent);
}
protected void onDestroy(){
unregisterReceiver(receiver);
super.onDestroy();
}
}

Example broadcast receiver invoking a service


public class ConnectivityReceiver extends BroadcastReceiver {
public void onReceive(Context context,Intent intent){
String message = "received";
Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
SharedPreferences preferences =
context.getSharedPreferences("service",Context.MODE_PRIVATE);
boolean started = preferences.getBoolean("started",false);
SharedPreferences.Editor editor = preferences.edit();
if(!started){
Intent serviceIntent = new Intent(context,NotesDataSyncService.class);
context.startService(serviceIntent);
editor.putBoolean("started",true);
}
else{
Intent serviceIntent = new Intent(context,NotesDataSyncService.class);
context.stopService(serviceIntent);
editor.putBoolean("started",false);
}
editor.commit();
}
}

SMS Example

SMS received broadcast

android.provider.Telephony.SMS_RECEIVED
Ordered broadcast may be aborted by some
application
Requires permissions

android.permission.RECEIVE_SMS
android.permission.READ_SMS

Intent structure

Generally carries an array of PDUs, mapped to string pdus

public class SmsReceiver extends BroadcastReceiver {


SmsManager sms = SmsManager.getDefault();
public void onReceive(Context context,Intent intent){
Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String number = currentMessage.getDisplayOriginatingAddress();
String message = currentMessage.getDisplayMessageBody();
String text = "senderNum: "+ number + ", message: " + message;
Toast.makeText(context, text , Toast.LENGTH_LONG).show();
}
}
} catch (Exception e) {
}
}
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smd.messenger"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.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="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>

You might also like