Kebanyakan proses yang terjadi pada suatu aplikasi Android berjalan pada layer teratas (Foreground), berjalan diatas spesial Thread yang disebut UI Thread atau Main Thread. Hal ini dapat menyebabkan masalah jika suatu aplikasi harus menjalankan proses yang lama (long-running operations) pada UI Thread, karena hal tersebut dapat menganggu kecepatan UI suatu aplikasi, bahkan dapat menyebabkan System error. Untuk menghindari masalah tersebut android telah menyediakan beberapa class yang dapat menjalankan suatu proses pada thread terpisah dan berjalan pada background aplikasi. Salah satu class tersebut adalah IntentService.
Dibawah ini merupakan contoh penggunaan IntentService pada pemrograman android. Pertama sebuah Activity (MainActivity.java) akan mengambil referensi terhadap file .txt dari system, kemudian Activity tersebut akan mengirimkan path absoluth sebagai String kepada sebuah IntentService (Services.java). IntentService akan membaca file tersebut kemudian mengembalikan isi file sebagai String ke Activity, selanjutnya Activity akan menampilkan isi file yang diterima dari IntentService pada sebuah TextView. Berikut source code nya:
src/com.me.intentservicesample/MainActivity.java
package com.me.intentservicesample; import java.net.URISyntaxException; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends ActionBarActivity { private static final int REQ_CODE = 0; //private ResponseReciever mResponseReciever = new ResponseReciever(); private BroadcastReceiver reciever = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Bundle bundle = intent.getExtras(); if (bundle != null) { String data = bundle.getString(Services.DATA); int status = bundle.getInt(Services.STATUS); if (status == RESULT_OK) { //MainActivity mainActivity = new MainActivity(); Toast.makeText(MainActivity.this, "Finished", Toast.LENGTH_LONG).show(); updateTextView(data); } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } } @Override protected void onResume() { super.onResume(); IntentFilter intentFilter = new IntentFilter(Services.ACTION_BROADCAST); //intentFilter.addDataScheme("text/plain"); LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver( reciever, intentFilter); } @Override protected void onPause() { super.onPause(); LocalBroadcastManager.getInstance(MainActivity.this) .unregisterReceiver(reciever); } /** private class ResponseReciever extends BroadcastReceiver { @Override public void onReceive(Context ctx, Intent intent) { // TODO Auto-generated method stub Bundle bundle = intent.getExtras(); if (bundle != null) { String data = bundle.getString(Services.DATA); int status = bundle.getInt(Services.STATUS); if (status == RESULT_OK) { //MainActivity mainActivity = new MainActivity(); Toast.makeText(MainActivity.this, "Finished", Toast.LENGTH_LONG).show(); //mainActivity.updateTextView(data); } } } } */ protected void updateTextView(String data) { TextView tv = (TextView) findViewById(R.id.textView); tv.setText(data.toString()); } /** called when button "Open a File" clicked */ public void openFile(View v) { // use implicit Intent to open a file Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/.txt"); intent.addCategory(Intent.CATEGORY_OPENABLE); try { startActivityForResult( Intent.createChooser(intent, "Select a file txt"), REQ_CODE); } catch (android.content.ActivityNotFoundException ex) { Toast.makeText(getBaseContext(), "You a need a File Manager", Toast.LENGTH_LONG).show(); ex.printStackTrace(); } } @Override protected void onActivityResult(int reqCode, int resultCode, Intent data) { // check activity result base on reqCode // reqCode must be same as REQ_CODE switch (reqCode) { case REQ_CODE: if (resultCode == RESULT_OK) { // get Uri data from intent Uri uri = data.getData(); String path = null; try { // convert Uri to file path (String) path = getPath(getBaseContext(), uri); // send the file path to Service this.sendToService(path); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** called to start the Service */ private void sendToService(String s) { // create an explicit Intent for the Service Intent intentService = new Intent(MainActivity.this, Services.class); intentService.putExtra(Services.PATH, s); startService(intentService); } public static String getPath(Context context, Uri uri) throws URISyntaxException { if ("content".equalsIgnoreCase(uri.getScheme())) { String[] projection = { "_data" }; Cursor cursor = null; try { cursor = context.getContentResolver().query(uri, projection, null, null, null); int column_index = cursor.getColumnIndexOrThrow("_data"); if (cursor.moveToFirst()) { return cursor.getString(column_index); } } catch (Exception e) { e.printStackTrace(); } } else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } } }
src/com.me.intentservicesample/Services.java
package com.me.intentservicesample; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.app.IntentService; import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; public class Services extends IntentService { private static int mStatus = Activity.RESULT_CANCELED; public static final String PATH = "com.me.intentservicesample.PATH"; public static final String ACTION_BROADCAST = "com.me.intentservicesample.BROADCAST"; public static final String STATUS = "com.me.intentservicesample.STATUS"; public static final String DATA = "com.me.intentservicesample.DATA"; public Services() { super("Services"); // TODO Auto-generated constructor stub } @Override protected void onHandleIntent(Intent intent) { // TODO Auto-generated method stub // get data from incoming intent String filePath = intent.getStringExtra(PATH); String fileContent = this.readFile(filePath); if (fileContent != null) { // report the work status to registered components publishResult(mStatus, fileContent); } } private void publishResult(int status, String data) { Intent localIntent = new Intent(Services.ACTION_BROADCAST); localIntent.putExtra(Services.STATUS, status); localIntent.putExtra(Services.DATA, data); LocalBroadcastManager.getInstance(Services.this).sendBroadcast( localIntent); } /** read the incoming file to get the file content as String */ private String readFile(String path) { File file = new File(path); int i, j = 0; byte[] data = new byte[(int) file.length()]; String string = null; InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(file)); while ((i = in.read()) != -1) { data[j++] = (byte) i; } string = byteToString(data).toString(); mStatus = Activity.RESULT_OK; return string; } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { // TODO Auto-generated catch block ex.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return string; } /** called to cast byte array to String */ private static String byteToString(byte[] b) { char[] c = new char[b.length]; StringBuilder sb = new StringBuilder(); for (int i = 0; i < c.length; i++) { c[i] = (char) b[i]; sb.append(c[i]); } return sb.toString(); } }
res/layout/activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.me.intentservicesample.MainActivity" tools:ignore="MergeRootFrame" />
res/layout/fragment_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: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="com.me.intentservicesample.MainActivity$PlaceholderFragment" > <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:onClick="openFile" android:text="Open a File" /> <LinearLayout android:id="@+id/linear" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/button" android:orientation="vertical" > <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="10dp" android:singleLine="false" android:text="@string/hello_world" /> </LinearLayout> </RelativeLayout>
IntentServiceManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.me.intentservicesample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <service android:name="com.me.intentservicesample.Services" android:exported="false" > </service> <activity android:name="com.me.intentservicesample.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> </application> </manifest>
Note: contoh aplikasi diatas membutuhkan sebuah File Manager dan sebuah file .txt yang akan dibaca oleh aplikasi.
Dibawah ini adalah tampilan aplikasi pada saat dijalankan.
Tampilan utama aplikasi:
Pada saat button "Open a File" di pilih:
Isi dari sebuah file .txt ditampilkan pada sebuah TextView:
Source: Android Developer
No comments:
Post a Comment