24
1 Islamic University of Gaza Faculty of Engineering Computer Engineering Department Mobile Computing ECOM 5341 By Eng. Wafaa Audah Aug. 2013

Eng. Wafaa Audahsite.iugaza.edu.ps/wp-content/uploads/Android-Lab7...3 Service Class Starting services An Android component (service, receiver, activity) can start and trigger a service

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

  • 1

    Islamic University of Gaza

    Faculty of Engineering

    Computer Engineering Department

    Mobile Computing ECOM 5341

    By

    Eng. Wafaa Audah

    Aug. 2013

  • 2

    Services, AlarmManager,

    Notifications and Widgets

    Android Services

    Service

    A service is a component which runs in the background, without direct interaction with the user. The Android platform provides and runs predefined system services and every Android application can use them.

    An Android application can, in addition to consuming the existing Android platform services, define and use new services.

    Android Platform Service

    The Android platform provides pre-defined services, usually exposed via a specific Manager class. Access to them can be gained via the getSystemService() method.

    Defining new services

    Every Android application can define and start new services

    Defining your own services allows you to design very responsive applications. You can fetch the application via a service and once the application is started by the user, it can present fresh data to the user.

    Declaring own services

    A service needs to be declared in the AndroidManifest.xml and the implementing class must extend the Service class or one of its subclasses. The following code shows an example for a service declaration and its implementation:

  • 3

    Service Class

    Starting services

    An Android component (service, receiver, activity) can start and trigger a service via the startService(intent) method. This method call starts the service if it is not running.

    - If the service started the onCreate() method is called.

    - Once the service is started the method call to start the service triggers

    startService(intent) method in the service. It passes in the Intent for the startService(intent) call.

    - If startService(intent) is called while the service is running, its onStartCommand() is also called. Therefore your service needs to be prepared that onStartCommand() can be called several times.

    - Alternatively to startService(intent) you can also start a service via the bindService() method call. This allows you to communicate directly with the service.

    public class MyService extends Service {

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

    //TODO do something useful

    return Service.START_NOT_STICKY;

    }

    @Override

    public IBinder onBind(Intent intent) {

    //TODO for communication return IBinder implementation

    return null;

    }

    }

    Intent service = new Intent(MyActivity.this, MyService.class);

    startService(service);

  • 4

    Stopping a service

    - You stop a service via the stopService() method. No matter how frequently you started the service with startService(intent) a call to stopService() stops it.

    - A service can stop itself by calling the stopSelf() method.

    Binding between activities and local services

    - onStartCommand(): is called whenever the Service is started using startService,

    so it may be executed several times within a Service’s lifetime.

    - startService() also allows you to provide a flag which determines the restart behavior of the services. Service.START_STICKY is used for services which are explicit started or stopped. If these services are terminated by the Android system, they are restarted if sufficient resources are available again.

    - Services started with Service.START_NOT_STICKY are not automatically restarted if terminated by the Android system.

    Service Class

    public class MyService extends Service{ private static final String TAG = "MyService"; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { Toast.makeText(this, "Congrats! MyService Created", Toast.LENGTH_LONG).show(); Log.d(TAG, "onCreate"); } @Override public void onStart(Intent intent, int startId) { } @Override public void onDestroy() { Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show(); Log.d(TAG, "onDestroy"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Toast.makeText(this,intent.getStringExtra("pass"),Toast.LENGTH_SHORT) .show(); return START_Not_STICKY; }}

  • 5

    Activity Class

    >

    public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button1 = (Button)findViewById(R.id.start_service); Button button2 = (Button)findViewById(R.id.stop_service); final EditText editText = (EditText)findViewById(R.id.editText1); final Intent i = new Intent(MainActivity.this, MyService.class); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub i.putExtra("pass", editText.getText().toString()); startService(i); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub stopService(i); } }); } }

  • 6

    Main.xml

  • 7

    AndroidManifest.xml

    Add this line

    Download ServiceExample Project Code

    Starting services regularly via AlarmManager

    As with activities the Android system may terminate the process of a service at any time to save resources. For this reason you cannot simple use a TimerTask *** in the service to ensure that it is executed on a regular basis.

    For correct scheduling of the Service use the AlarmManager class. The following code demonstrates how to do this.

    *** FOR Repeated Tasks in a Service

    Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { public void run() {

    //your code here } }, 0, 1000);

    //0 : when to start

    //1000 : time between repetition in milliseconds

    // to stop:

    timer.cancel();

    Calendar cal = Calendar.getInstance();

    Intent intent = new Intent(this, MyService.class);

    PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);

    AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

    // Start every 30 seconds

    alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000,

    pintent);

    http://www.mediafire.com/download/obftcu11via9du1/ServiceExample.rarhttp://www.mediafire.com/download/obftcu11via9du1/ServiceExample.rar

  • 8

    AlarmManager

    Many times we want some task to be performed at some later time in future. For Example: In SMS Scheduler we want a SMS to be sent at some later time, or Task Reminder in which we want to be reminded about a task at a particular time, to implement all these things we use AlarmManager class.

    - AlarmManager class provides access to the system alarm services.

    - These allow you to schedule your application to be run at some point in the future.

    - When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running.

    - Registered alarms are retained while the device is asleep (and can optionally wakes the device up if they go off during that time).

    >

    Service Class

    The only changed part according to the previous example

    @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Toast.makeText(this,"Welcome :)", Toast.LENGTH_SHORT).show(); return START_NOT_STICKY; // no automatic restart }

  • 9

    Activity Class

    Download ServiceWithAlarmExample Code

    public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button1 = (Button)findViewById(R.id.start_service); Button button2 = (Button)findViewById(R.id.stop_service); final Intent i = new Intent(this, MyService.class); final PendingIntent pintent = PendingIntent.getService(this, 0, i, 0); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Calendar cal = Calendar.getInstance(); AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE); // Start every 30 seconds alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis()+10*1000, 10*1000, pintent); startService(i); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub alarm.cancel(pintent); stopService(i); } }); } }

    http://www.mediafire.com/download/wht8e6b97vdxk4w/ServiceWithAlarmExample.rar

  • 10

    General use of Alarm Manager

    - Alarms are a means of firing Intents at pre-determined times or intervals.

    - Unlike Timers, Alarms operate outside the scope of your application, so you can use them to trigger application events or actions even after your application has been closed.

    - Alarms are particularly powerful when used in combination with Broadcast Receivers, enabling you to set Alarms that fire broadcast Intents, start Services, or even open Activities, without your application needing to be open or running.

    One-Shot Alarm

    To create a new one-shot Alarm, use the set method and specify an alarm type, a trigger time, and a Pending Intent to fire when the Alarm triggers. If the trigger time you specify for the Alarm occurs in the past, the Alarm will be triggered immediately. There are four alarm types that are available, we will use: RTC_WAKEUP — wakes the device from sleep to fire the Pending Intent at the clock time specified. Setting Repeating Alarmss

    - Repeating alarms work in the same way as the one-shot alarms but will trigger repeatedly at the specified interval.

    To set a repeating alarm, use the setRepeating method on the Alarm Manager.

    - This methods supports an alarm type, an initial trigger time, and a Pending Intent to fire when the alarm triggers (as described in the previous section).

    - Use setRepeating when you need fine-grained control over the exact interval of your repeating alarm. The interval value passed in to this method lets you specify an exact interval for your alarm, down to the millisecond.

  • 11

    Example

    Layout: - two EditText with whom you can set the delay time for the first alarm and the delay

    between alarms in repeating mode

    - an EditText (not editable) that visualize a counter for received alarms

    - three Button: one to start a single alarm, one to start repeting alarms and one to stop alarms

    in repeating mode

    Code:

    - BroadcastReceiver: it receives the intent sent as alarms an send a message to an handler

    - Handler: it receives a message and if it's an alarm it refresh "Received Alarms" and shows a

    toast

    - PendingIntent: with whom you notify the action to AlarmManager

    - AlarmManager: you ask to it the type of alarm that you desire (one shot or repeating) or

    cancel an active repeating alarm

  • 12

    public class AlarmManagerTutorialActivity extends Activity { private static final String ALARM_REFRESH_ACTION = "it.trento.alchemiasoft.casagranda.simone.alarmmanagertutorial.ALARM_REFRESH_ACTION"; private static final int ALARM_CODE = 20; private static final long DEFAULT_START_DELAY = 1000; private static final long DEFAULT_INTERVAL_DELAY = 3000; private BroadcastReceiver alarmReceiver; private PendingIntent pendingIntent; private AlarmManager alarmManager; private int alarmCounted; // UI references private EditText millsStartEditText, millsIntervalEditText, alarmsReceived; // The handler that manage the UI updates private Handler myHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case ALARM_CODE: alarmsReceived.setText(String.valueOf(alarmCounted)); Toast.makeText(AlarmManagerTutorialActivity.this, "Alarm Received", Toast.LENGTH_SHORT).show(); break; default: break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // We retrieve UI references millsStartEditText = (EditText) findViewById(R.id.millsStartEditText); millsIntervalEditText = (EditText) findViewById(R.id.millsIntervalsEditText); alarmsReceived = (EditText) findViewById(R.id.alarmsReceivedEditText); } @Override protected void onStart() { super.onStart(); // We get the AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); // We set default parameters for alarms millsStartEditText.setText(String.valueOf(DEFAULT_START_DELAY)); millsIntervalEditText.setText(String.valueOf(DEFAULT_INTERVAL_DELAY)); // We prepare the pendingIntent for the AlarmManager Intent intent = new Intent(ALARM_REFRESH_ACTION); pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); // We create and register a broadcast receiver for alarms alarmReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We increment received alarms alarmCounted++; // We notify to handler the arrive of alarm Message msg = myHandler.obtainMessage(ALARM_CODE, intent); myHandler.sendMessage(msg); } }; // We register dataReceiver to listen ALARM_REFRESH_ACTION IntentFilter filter = new IntentFilter(ALARM_REFRESH_ACTION); registerReceiver(alarmReceiver, filter); }

  • 13

    Download AlarmManagerTutorial Code

    public void startOneShot(View v) { // We get value for one shot alarm int startTime = Integer.parseInt(millsStartEditText.getText() .toString()); // We have to register to AlarmManager Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.MILLISECOND, startTime); // We set a one shot alarm alarmManager.set(AlarmManager.RTC_WAKEUP, calendar .getTimeInMillis(), pendingIntent); } public void startRepeating(View v) { // We get value for repeating alarm int startTime = Integer.parseInt(millsStartEditText.getText() .toString()); long intervals = Long.parseLong(millsIntervalEditText.getText() .toString()); // We have to register to AlarmManager Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.MILLISECOND, startTime); // We set a repeating alarm alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar .getTimeInMillis(), intervals, pendingIntent); } public void stopAlarms(View v) { // We cancel alarms that matches with pending intent alarmManager.cancel(pendingIntent); Toast.makeText(this, "Alarms stopped", Toast.LENGTH_SHORT).show(); } }

    http://www.mediafire.com/download/u0qph1vw6nonpx4/AlarmManagerTutorial.rar

  • 14

    Notifications

    Notification Manager

    Android allows putting notification into the title bar of your application. The user can expand the notification bar and by selecting the notification the user can trigger another activity.

    Setting up Notifications

    Notifications in Android are represented by the Notification class. To create notifications you use the NotificationManager class which can be received from the Context, e.g. an activity or a service, via the getSystemService() method.

    - The Notification.Builder provides a builder interface to create an Notification object.

    - You use a PendingIntent to specify the action which should be performed once the user selects the notification.

    Set the icon, scrolling text and timestamp

    Pending Intent A PendingIntent is a token that you give to another application (e.g. Notification Manager, Alarm Manager or other 3rd party applications), which allows this other application to use the permissions of your application to execute a predefined piece of code.

    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    Notification notification = new Notification(R.drawable.android, text, System.currentTimeMillis());

  • 15

    Canceling Notifications

    The user can dismiss all notification or if you set your notification to auto-cancel it is also removed once the user selects it.

    You can also call the cancel() for a specific notification ID on the NotificationManager. The cancelAll() method call removes all of the notifications you previously issued.

    notificationManager.cancel(notificationID);

    // Text to display in the extended status window String expandedText = "Extended text"; // Title for the expanded status String expandedTitle = "Notification Title"; // Intent to launch an activity when the extended text is clicked Intent intent = new Intent(this, second.class); PendingIntentlaunchIntent=PendingIntent.getActivity(this,0,intent,0); notification.setLatestEventInfo(this,expandedTitle, expandedText, launchIntent); int notificationID=1; notificationManager.notify(notificationID, notification);

  • 16

    Example

    When service

    started, it

    appears

    When expanded

  • 17

    ServiceLauncher Class

    public class ServiceLauncher extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.servicelauncher); Button start = (Button)findViewById(R.id.startButton); Button stop = (Button)findViewById(R.id.stopButton); start.setOnClickListener(startListener); stop.setOnClickListener(stopListener); } private OnClickListener startListener = new OnClickListener() { public void onClick(View v){ startService(new Intent(ServiceLauncher.this,NotifyService.class)); } }; private OnClickListener stopListener = new OnClickListener() { public void onClick(View v){ stopService(new Intent(ServiceLauncher.this,NotifyService.class)); } };

    }

  • 18

    NotifyService Class

    public class NotifyService extends Service { int notificationID=1; private Long counter = 0L; private NotificationManager nm; private Timer timer = new Timer(); private final Calendar time = Calendar.getInstance(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { super.onCreate(); nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); Toast.makeText(this,"Service created at " + time.getTime(), Toast.LENGTH_LONG).show(); showNotification(); incrementCounter(); } @Override public void onDestroy() { super.onDestroy(); // Cancel the persistent notification. shutdownCounter(); nm.cancel(notificationID); Toast.makeText(this, "Service destroyed at " + time.getTime() + "; counter is at: " + counter, Toast.LENGTH_LONG).show(); counter=null; } /** * Show a notification while this service is running. */ private void showNotification() { // Text to display the apparent name of the notification:Title for the expanded status String NotiName = "TestNotification"; // Set the icon, scrolling text and timestamp Notification notification = new Notification(R.drawable.android, NotiName,System.currentTimeMillis()); // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ServiceLauncher.class), 0);

  • 19

    Download ServiceNotification Code

    // Set the info for the views that show in the notification panel. // Text to display in the extended status window String expandedText = "Service started Successfully, Go to stop buttin if you want to stop it "; notification.setLatestEventInfo(this, NotiName, expandedText, contentIntent); // Send the notification. // We use a layout id because it is a unique number. We use it later to cancel. nm.notify(notificationID, notification); } private void incrementCounter() { timer.scheduleAtFixedRate(new TimerTask(){ public void run() {counter++;}}, 0, 1000); } private void shutdownCounter() { if (timer != null) { timer.cancel(); } }

    }

    http://www.mediafire.com/download/81yqo7cwwcs6dem/ServiceNotification.rar

  • 20

    App Widgets

    Overview about AppWidgets

    - Widgets are little applications which can be placed on a widget host, typically the homescreen or the lockscreen, of your Android device.

    - A Widget runs as part of the process of its host. This requires that Widgets preserve the permissions of their application.

    - Widgets use RemoteViews to create there user interface. A RemoteView can be executed by another process with the same permissions as the original application. This way the Widget runs with the permissions of its defining application.

    - The user interface for a Widget is defined by a BroadcastReceiver. This BroadcastReceiver inflates its layout into an object of type RemoteViews. This RemoteViews object is delivered to Android, which hands it over the HomeScreen application.

    AppWidget Framework

    AppWidgetProviderInfo object: - Describes the metadata for an App Widget, such as the App Widget's layout,

    update frequency, and the AppWidgetProvider class.

    - This should be defined in XML.

    AppWidgetProvider class: - Defines the basic methods that allow you to programmatically interface with the

    App Widget, based on broadcast events. (AppWidgetProvider class is a child class of BroadcastReceiver class).

    - Through it, you will receive broadcasts when the App Widget is updated, enabled, disabled and deleted.

    View layout - Defines the initial layout for the App Widget, defined in XML.

    Additionally, you can implement an App Widget configuration Activity. - This is an optional Activity that launches when the user adds your App Widget

    and allows him or her to modify App Widget settings at create-time.

  • 21

    Steps to create a Widget

    In order to create a Widget, you will:

    1. Declare an AppWidgetProvider in the Manifest file (Widget configuration).

    2. Create a BroadcastReceiver which is used to build the user interface of the Widget.

    3. Create the AppWidgetProviderInfo Metadata XML file which describes the properties of the widget (metadata file in a new folder called xml folder inside res folder).

    4. Create the App Widget Layout XML file.

    >

  • 22

    App Widget layouts are based on RemoteViews, which do not support every kind of layout or view widget.

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_demo);

    5. Write the AppWidgetProvider Class.

    public class MyWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager,

    int[] appWidgetIds) { }

    MyWidgetProvider Class

    public class MyWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_demo); remoteViews.setOnClickPendingIntent(R.id.widget_button, buildButtonPendingIntent(context)); pushWidgetUpdate(context, remoteViews); } public static PendingIntent buildButtonPendingIntent(Context context) { Intent intent = new Intent(); intent.setAction("pl.looksok.intent.action.CHANGE_PICTURE"); return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } public static void pushWidgetUpdate(Context context, RemoteViews remoteViews) { ComponentName myWidget = new ComponentName(context, MyWidgetProvider.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); // Tell the manager to perform an update on the current app widget manager.updateAppWidget(myWidget, remoteViews); } }

  • 23

    MyWidgetIntentReceiver Class

    public class MyWidgetIntentReceiver extends BroadcastReceiver { private static int clickCount = 0; @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals("pl.looksok.intent.action.CHANGE_PICTURE")){ updateWidgetPictureAndButtonListener(context); } } private void updateWidgetPictureAndButtonListener(Context context) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_demo); remoteViews.setImageViewResource(R.id.widget_image, getImageToSet()); //REMEMBER TO ALWAYS REFRESH YOUR BUTTON CLICK LISTENERS!!! remoteViews.setOnClickPendingIntent(R.id.widget_button, MyWidgetProvider.buildButtonPendingIntent(context)); MyWidgetProvider.pushWidgetUpdate(context.getApplicationContext(), remoteViews); } private int getImageToSet() { clickCount++; return clickCount % 2 == 0 ? R.drawable.pink : R.drawable.green; } }

  • 24

    Download WidgetDemo Code

    SEE YOU AT THE NEXT LAB

    http://www.mediafire.com/download/rs2wimxssd9oir8/WidgetDemo.rar