Service
theory, through that you can see the components that build up the Service
and it's clients, now we are going to see some examples using the Service
and the way how the these scenario executed.IntentServices for one time tasks: Download File Service
IntentService
class for your service implementation.The
IntentService
is used to perform a certain task in the background. Once done, the instance of IntentService
terminates itself automatically. An example for its usage would be downloading certain resources from the internet.The
IntentService
class offers onHandleIntent()
method which will be asynchronously called by the Android system.DEMO VIDEO:
Firstly in this "download file by
Service
" project, creating an activity layout file simple like this:
activity_main.xml
Now, go to programmatically code, as note above, we must create a subclass of <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_horizontal_margin">
<Button
android:id="@+id/btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="30dp"
android:text="Download" />
<TextView
android:id="@+id/text_view"
android:textColor="@android:color/holo_green_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Status"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/download_status"
android:layout_width="wrap_content"
android:textColor="@android:color/holo_blue_dark"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/text_view"
android:layout_alignRight="@+id/btn_download"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
IntentService
, mean that this Service
run one time and auto destroy after finish downloading file process.By using this Service type, the most important work is overriding the
onHandleIntent()
, in this example, we create an InputStream
to get data from an URL (a PNG image):
DownloadService.java
Note: As you see in code, we publish download result (Error or Success) to UI thread by package devexchanges.info.downloadservice;
import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
public class DownloadService extends IntentService {
public static final String URL = "url";
public static final String FILENAME = "name";
public static final String FILEPATH = "path";
public static final String RESULT = "result";
public static final String NOTIFICATION = "notification";
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
String urlPath = intent.getStringExtra(URL);
String fileName = intent.getStringExtra(FILENAME);
int result = Activity.RESULT_CANCELED;
try {
URL url = new URL(urlPath);
InputStream input = url.openStream();
//The sdcard directory e.g. '/sdcard' can be used directly, or
//more safely abstracted with getExternalStorageDirectory()
File storagePath = new File(Environment.getExternalStorageDirectory() + "/Pictures");
OutputStream output = new FileOutputStream(new File(storagePath, fileName));
try {
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
result = Activity.RESULT_OK;
} finally {
output.close();
input.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
publishResults(result);
}
private void publishResults(int result) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}
}
BroadcastReceiver
. In Service
class, this action will invoke by call sendBroadcast(Intent)
.In this activity, we will talk more clearly about the
BroadcastReceiver
. Declaring an instance to receive the Service
result and update data to views, overriding onReceive()
is required, receiving Bundle
put from Service
here:
private BroadcastReceiver receiver = new BroadcastReceiver() {
@SuppressLint("SetTextI18n")
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
int resultCode = bundle.getInt(DownloadService.RESULT);
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this, "File downloaded!", Toast.LENGTH_LONG).show();
downloadStatus.setText("Download completed!");
} else {
Toast.makeText(MainActivity.this, "Error Downloading process!", Toast.LENGTH_LONG).show();
downloadStatus.setText("Download failed!");
}
}
}
};
With BroadcastReceiver
, we must register it in onResume()
and unregistering it in onPause()
:
@Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
In this project, we start download process after click at a Button
, save file (image) to SD card, this is full code for this activity:
MainActivity.java
And this is output screens:
package devexchanges.info.downloadservice;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private TextView downloadStatus;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadStatus = (TextView) findViewById(R.id.download_status);
Button btnDownload = (Button) findViewById(R.id.btn_download);
btnDownload.setOnClickListener(onDownloadListener());
}
private View.OnClickListener onDownloadListener() {
return new View.OnClickListener() {
@SuppressLint("SetTextI18n")
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, DownloadService.class);
intent.putExtra(DownloadService.FILENAME, "logo.png");
intent.putExtra(DownloadService.URL, "http://i.imgur.com/cReBvDB.png");
startService(intent);
downloadStatus.setText("Downloading...");
}
};
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@SuppressLint("SetTextI18n")
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
int resultCode = bundle.getInt(DownloadService.RESULT);
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this, "File downloaded!", Toast.LENGTH_LONG).show();
downloadStatus.setText("Download completed!");
} else {
Toast.makeText(MainActivity.this, "Error Downloading process!", Toast.LENGTH_LONG).show();
downloadStatus.setText("Download failed!");
}
}
}
};
}
INTERNET
and WRITE_EXTERNAL_STORAGE
permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You can view full project code on @Github.
Unbounded Service: Audio Player
Button
(to Start and Stop playing Music):
activity_main.xml
Layout preview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="devexchanges.info.mediaplayerservice.MainActivity">
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startPlayer"
android:text="Start the Player" />
<Button
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_start"
android:text="Stop the Player" />
</RelativeLayout>
We will create a
Service
's subclass and overriding some necessary methods. In onBind()
we will return an IBinder
instance (may be null
), because onStartCommand()
will be overridden, starting MediaPlayer
here:
MediaPlayerService.java
Back to the activity code, we will start/stop package devexchanges.info.mediaplayerservice;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
public class MediaPlayerService extends Service {
private MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.canon_in_d);
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
@Override
public void onDestroy() {
player.stop();
player.release();
}
@Override
public void onLowMemory() {
}
}
Service
by clicking 2 Buttons
:
MainActivity.java
This app not require any special permission. From now on, when you click Start button, app will play your audio file, and as you see in the activity code, I used package devexchanges.info.mediaplayerservice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private View btnStart;
private View btnStop;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.btn_start);
btnStop = findViewById(R.id.btn_stop);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startPlayer(v);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopPlayer(v);
}
});
}
public void startPlayer(View v) {
Intent i = new Intent(this, MediaPlayerService.class);
startService(i);
}
public void stopPlayer(View v) {
stopService(new Intent(this, MediaPlayerService.class));
}
}
startService()
(bindService()
), so this Service
will always run in the background even your activity destroyed. It's only stop when you hit stop button.
Note: Audio resource files must be put in res/raw folder. All Android Supported Media format you can find out here!
Conclusions
Service
in Android corresponding to 2 Service types: IntentService
and normal (Unbounded) Service
. I hope that you can help you to understand the philosophy of Service
action. Further, you can go to these official docs to reading more:- Service reference: http://developer.android.com/reference/android/app/Service.html
- Service guide: http://developer.android.com/guide/components/services.html
- BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
Next Chapter
|