In this part of my Android tutorial we cover how to use Intent Services, Broadcasts, Broadcast Receivers, Intent Filters and how to download, save and read files.
I did my best to keep all of the code separated so that you can easily copy and paste out the functionality you need with your Android apps. All of the code follows the video with a ton of comments.
If you like videos like this it helps to tell Google Plus with a click here [googleplusone]
Code From the Video
activity_main.xml
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Download File"
android:id="@+id/startServiceButton"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="startFileService"/>
<EditText
android:layout_width="match_parent"
android:layout_height="350dp"
android:inputType="textMultiLine"
android:ems="10"
android:id="@+id/downloadedEditText"
android:layout_below="@+id/startServiceButton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="41dp" />
</RelativeLayout>
MainActivity.java
package com.newthinktank.derekbanas.serviceex;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
// IntentService : Uses an intent to start a background service so as not to disturb the UI
// Android Broadcast : Triggers an event that a BroadcastReceiver can act on
// BroadcastReceiver : Acts when a specific broadcast is made
public class MainActivity extends Activity {
EditText downloadedEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadedEditText = (EditText) findViewById(R.id.downloadedEditText);
// Allows use to track when an intent with the id TRANSACTION_DONE is executed
// We can call for an intent to execute something and then tell use when it finishes
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(FileService.TRANSACTION_DONE);
// Prepare the main thread to receive a broadcast and act on it
registerReceiver(downloadReceiver, intentFilter);
}
public void startFileService(View view) {
// Create an intent to run the IntentService in the background
Intent intent = new Intent(this, FileService.class);
// Pass the URL that the IntentService will download from
intent.putExtra("url", "https://www.newthinktank.com/wordpress/lotr.txt");
// Start the intent service
this.startService(intent);
}
// Is alerted when the IntentService broadcasts TRANSACTION_DONE
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
// Called when the broadcast is received
@Override
public void onReceive(Context context, Intent intent) {
Log.e("FileService", "Service Received");
showFileContents();
}
};
// Will read our local file and put the text in the EditText
public void showFileContents(){
// Will build the String from the local file
StringBuilder sb;
try {
// Opens a stream so we can read from our local file
FileInputStream fis = this.openFileInput("myFile");
// Gets an input stream for reading data
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
// Used to read the data in small bytes to minimize system load
BufferedReader bufferedReader = new BufferedReader(isr);
// Read the data in bytes until nothing is left to read
sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line).append("\n");
}
// Put downloaded text into the EditText
downloadedEditText.setText(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileService.java
package com.newthinktank.derekbanas.serviceex;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
// We use an IntentService to handle long running processes off the UI thread
// Any new requests will wait for the 1st to end and it can't be interrupted
public class FileService extends IntentService {
// Used to identify when the IntentService finishes
public static final String TRANSACTION_DONE = "com.newthinktank.TRANSACTION_DONE";
// Validates resource references inside Android XML files
public FileService() {
super(FileService.class.getName());
}
public FileService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.e("FileService", "Service Started");
// Get the URL for the file to download
String passedURL = intent.getStringExtra("url");
downloadFile(passedURL);
Log.e("FileService", "Service Stopped");
// Broadcast an intent back to MainActivity when file is downloaded
Intent i = new Intent(TRANSACTION_DONE);
FileService.this.sendBroadcast(i);
}
protected void downloadFile(String theURL) {
// The name for the file we will save data to
String fileName = "myFile";
try{
// Create an output stream to write data to a file (private to everyone except our app)
FileOutputStream outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
// Get File
URL fileURL = new URL(theURL);
// Create a connection we can use to read data from a url
HttpURLConnection urlConnection = (HttpURLConnection) fileURL.openConnection();
// We are using the GET method
urlConnection.setRequestMethod("GET");
// Set that we want to allow output for this connection
urlConnection.setDoOutput(true);
// Connect to the url
urlConnection.connect();
// Gets an input stream for reading data
InputStream inputStream = urlConnection.getInputStream();
// Define the size of the buffer
byte[] buffer = new byte[1024];
int bufferLength = 0;
// read reads a byte of data from the stream until there is nothing more
while ( (bufferLength = inputStream.read(buffer)) > 0 ){
// Write the data received to our file
outputStream.write(buffer, 0, bufferLength);
}
// Close our connection to our file
outputStream.close();
// Get File Done
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.newthinktank.derekbanas.serviceex" >
<!-- We need permission to access the internet -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Declare the service -->
<service
android:name=".FileService"
android:exported="false" />
</application>
</manifest>