lecture12 (2)
lecture12 (2)
Sensor Programming
Lecture 12
Wenbing Zhao
Department of Electrical Engineering and Computer
Science
Cleveland State University
[email protected]
8/16/21
Services
How to create a service that runs in the
background
How to perform long-running tasks in a
separate thread
How to perform repeated tasks in a service
How an activity and a service
communicate
8/16/21
What is a Service
A facility for the application to tell the system
about something it wants to be doing in the
background
Even when the user is not directly interacting with the
application
This corresponds to calls to Context.startService(), which
ask the system to schedule work for the service, to be run
until the service or someone else explicitly stop it
A facility for an application to expose some of its
functionality to other applications
This corresponds to calls to Context.bindService(), which
allows a long-standing connection to be made to the
service in order to interact with it
8/16/21
What is a Service
A Service is not a separate process. The Service
object itself does not imply it is running in its own
process; unless otherwise specified, it runs in the
same process as the application it is part of
A Service is not a thread. It is not a means itself to
do work off of the main thread
8/16/21
Service Lifecycle
If someone calls Context.startService() then the system will
retrieve the service and then call its
onStartCommand(Intent, int, int) method with the arguments
supplied by the client
The service will at this point continue running until
Context.stopService() or stopSelf() is called
There are two major modes of operation depending on the
value they return from onStartCommand():
START_STICKY is used for services that are explicitly started and stopped
as needed
START_NOT_STICKY or START_REDELIVER_INTENT are used for services
that should only remain running while processing any commands sent to
them
8/16/21
Service Permission
Global access to a service can be enforced when it is
declared in its manifest's <service> tag
By doing so, other applications will need to declare a
corresponding <uses-permission> element in their own
manifest to be able to start, stop, or bind to the service
8/16/21
Basic Service
Basic steps of creating/using a service:
Create a separate service java class
Add service in the manifest
Start/stop the service from the main activity
Create a new project and name it Services
Modify manifest:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android=
http://schemas.android.com/apk/res/android package="com.wenbing.services">
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:theme="@style/AppTheme"> <activity
android:name=".MainActivity"> <intent-filter> <action
android:name="android.intent.action.MAIN" /> <category
android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<service android:name=".MyService" /> </application></manifest>
8/16/21
import android.app.Service;import
Basic Service
android.content.Intent;import
android.os.IBinder;import
android.widget.Toast;import
java.net.MalformedURLException;import
java.net.URL;import android.os.AsyncTask;
Add a new Java class: import android.util.Log;import
java.util.Timer;import java.util.TimerTask;
MyService
public class MyService extends Service { int counter = 0; static final int
UPDATE_INTERVAL = 1000; private Timer timer = new Timer(); @Override public IBinder
onBind(Intent arg0) { return null; } @Override public int onStartCommand(Intent intent,
int flags, int startId) { Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
doSomethingRepeatedly(); try { new DoBackgroundTask().execute( new
URL("http://www.amazon.com/somefiles.pdf"), new
URL("http://www.wrox.com/somefiles.pdf"), new
URL("http://www.google.com/somefiles.pdf"), new
URL("http://www.learn2develop.net/somefiles.pdf")); } catch (MalformedURLException e) {
e.printStackTrace(); } return START_STICKY; }
8/16/21
@Override public void onDestroy() { super.onDestroy(); if (timer != null){
timer.cancel(); } Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
} private void doSomethingRepeatedly() { timer.scheduleAtFixedRate(new TimerTask() {
public void run() { Log.d("MyService", String.valueOf(++counter)); } }, 0,
UPDATE_INTERVAL); } private class DoBackgroundTask extends AsyncTask<URL, Integer, Long>
{ protected Long doInBackground(URL... urls) { int count = urls.length; long
totalBytesDownloaded = 0; for (int i = 0; i < count; i++) { totalBytesDownloaded +=
DownloadFile(urls[i]); publishProgress((int) (((i + 1) / (float) count) * 100)); }
return totalBytesDownloaded; }
8/16/21
onProgressUpdate is invoked when you call publishProgress()
Call stopSelf() if you want to destroy the service as soon as the long-running
task is done
8/16/21
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
Basic Service xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
Modify layout: add tools:context="com.....services.MainActivity"> <Button
two buttons to android:text="Start Service"
android:layout_height="50dp"
android:layout_width="90dp"
8/16/21
Basic Service
Modify MainActivity.java: start/stop service
import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import
android.content.Intent;import android.view.View;public class MainActivity extends
AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }public void
startService(View view) { startService(new Intent(getBaseContext(), MyService.class)); }
public void stopService(View view) { stopService(new Intent(getBaseContext(),
MyService.class)); }}
8/16/21
Communication between Service and Activity
8/16/21
Communication between Service and Activity
import android.app.IntentService;import android.content.Intent;
import android.util.Log;import java.net.MalformedURLException;
import java.net.URL;public class MyIntentService extends
Populate IntentService { public MyIntentService() {
super("MyIntentServiceName"); } @Override protected void
MyIntentService.java onHandleIntent(Intent intent) { try { int result =
DownloadFile(new URL("http://www.amazon.com/somefile.pdf"));
Log.d("IntentService", "Downloaded " + result + " bytes");
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("FILE_DOWNLOADED_ACTION");
getBaseContext().sendBroadcast(broadcastIntent); } catch
(MalformedURLException e) { e.printStackTrace(); } }
private int DownloadFile(URL url) { try {
Thread.sleep(5000); } catch (InterruptedException e)
{ e.printStackTrace(); } return 100; }}
8/16/21
Communication between Service and Activity
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;import
android.content.BroadcastReceiver;import
Modify android.content.Context;import android.content.Intent;
import android.content.IntentFilter;import
MainActivity.java android.view.View;import android.widget.Toast;public
class MainActivity extends AppCompatActivity {
IntentFilter intentFilter; @Override protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }
@Override public void onResume() {
super.onResume(); intentFilter = new
IntentFilter();
intentFilter.addAction("FILE_DOWNLOADED_ACTION"
); //---register the receiver---
registerReceiver(intentReceiver, intentFilter); }
@Override public void onPause() {
super.onPause(); //---unregister the receiver---
unregisterReceiver(intentReceiver); }
intent to filter for file downloaded
intent
8/16/21
Communication between Service and Activity
Modify MainActivity.java
public void startService(View view) { startService(new
Intent(getBaseContext(), MyIntentService.class)); } public void
stopService(View view) { stopService(new
Intent(getBaseContext(), MyIntentService.class)); } private
BroadcastReceiver intentReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
Toast.makeText(getBaseContext(), "File downloaded!",
Toast.LENGTH_LONG).show(); } };}
8/16/21
Communication between Service and Activity
// Creates a new Intent to start a service. Passes a URI in the Intent's "data" field.
mServiceIntent = new Intent();mServiceIntent.putExtra("download_url", dataUrl));
8/16/21
Homework#10
Modify the Services app:
Use a ProgressBar view instead/in addition to the Toast to
display the progress made by the service
8/16/21