Sunday, March 31, 2013
Create your Treasure Map on Android
Refer to the post "Embed Google Map in WebView", you can create your own Treasure Map easily, by copy the link URL from http://maps.google.com/ with Treasure Mode selected, and replace it to mapPath in the MainActivity code.
Remark: I don't know will it back to normal tomorrow:)
FYI:
How to get Traffic come from International Space Station
If you have install Google Analytics, check your Real-Time report of Locations within today, you have 100% traffic from International Space Station!
Happy April Fools Day:)
Google Nose!? Is it a April Fools Joke?
Is it a April Fools Joke? http://www.google.com/nose/
Introducing Google Nose
We're excited to announce our newest addition to Search: Google Nose. What do wet dogs smell like? Google Nose! How about victory? Google Nose! Try searching on Google for "wet dog" and explore other smells that people sniffed for, or visit google.com/nose to learn more. Happy smelling!
Introducing Google Nose
We're excited to announce our newest addition to Search: Google Nose. What do wet dogs smell like? Google Nose! How about victory? Google Nose! Try searching on Google for "wet dog" and explore other smells that people sniffed for, or visit google.com/nose to learn more. Happy smelling!
ADK Example: Control Arduino Due LED from Android device
Example to show how to implement with ADK, to control LED on Arduino Due from Android device.
Refer to my another blog for Arduino:
Draw Polyline from touched location to MyLocation
[Remark@2015-11-01:
getMyLocation() method is deprecated.
use com.google.android.gms.location.FusedLocationProviderApi instead. FusedLocationProviderApi provides improved location finding and power usage and is used by the "My Location" blue dot. See the MyLocationDemoActivity in the sample applications folder for example example code, or the Location Developer Guide.]
In this exercise, Google Maps Android API v2 is implemented with MyLocation enabled. When user LongClick on the Map, a marker will be drawn, and a Polyline from touched location to MyLocation will be drawn if MyLocation is available.
To get MyLocation programmatically, you have to enable my-location layer by calling setMyLocationEnabled(true). Then call getMyLocation(), it returns the currently displayed user location, or null if there is no location data available. Please noted that MyLocation may be need long time to available.
MainActivity.java
layout
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
getMyLocation() method is deprecated.
use com.google.android.gms.location.FusedLocationProviderApi instead. FusedLocationProviderApi provides improved location finding and power usage and is used by the "My Location" blue dot. See the MyLocationDemoActivity in the sample applications folder for example example code, or the Location Developer Guide.]
In this exercise, Google Maps Android API v2 is implemented with MyLocation enabled. When user LongClick on the Map, a marker will be drawn, and a Polyline from touched location to MyLocation will be drawn if MyLocation is available.
To get MyLocation programmatically, you have to enable my-location layer by calling setMyLocationEnabled(true). Then call getMyLocation(), it returns the currently displayed user location, or null if there is no location data available. Please noted that MyLocation may be need long time to available.
MainActivity.java
package com.example.androidmapex;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;
import android.location.Location;
import android.os.Bundle;
import android.widget.Toast;
import android.app.Activity;
import android.app.FragmentManager;
public class MainActivity extends Activity{
private GoogleMap myMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager myFragmentManager = getFragmentManager();
MapFragment myMapFragment1 =
(MapFragment)myFragmentManager.findFragmentById(R.id.map1);
myMap = myMapFragment1.getMap();
myMap.setMyLocationEnabled(true);
myMap.setOnMapLongClickListener(myOnMapLongClickListener);
}
OnMapLongClickListener myOnMapLongClickListener =
new OnMapLongClickListener(){
@Override
public void onMapLongClick(LatLng point) {
myMap.addMarker(new MarkerOptions()
.position(point)
.title(point.toString()));
Location myLocation = myMap.getMyLocation();
if(myLocation == null){
Toast.makeText(getApplicationContext(),
"My location not available",
Toast.LENGTH_LONG).show();
}else{
PolylineOptions polylineOptions = new PolylineOptions();
polylineOptions.add(point);
polylineOptions.add(
new LatLng(myLocation.getLatitude(), myLocation.getLongitude()));
myMap.addPolyline(polylineOptions);
}
}
};
}
layout
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<fragment
android:id="@+id/map1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5px"
class="com.google.android.gms.maps.MapFragment"/>
</LinearLayout>
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
Saturday, March 30, 2013
Embed Google Map in WebView
To load your custom Map, open it in PC, copy the Short URL in share option. It will be used later.
MainActivity.java, load mapPath with the Short URL in share option.
package com.example.androidwebmap;
import android.os.Bundle;
import android.app.Activity;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
WebView myWebView;
String mapPath = "https://maps.google.com/?ll=37.0625,-95.677068&spn=29.301969,56.513672&t=h&z=4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = (WebView)findViewById(R.id.mapview);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.setWebViewClient(new WebViewClient());
myWebView.loadUrl(mapPath);
}
}
Modify layout to add a MapView.
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<WebView
android:id="@+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Notes:
- Permission of "android.permission.INTERNET" is need.
- Not all function can work on WebView! such as user cannot touch the marker on map.
Download the files.
Retain instance of MapFragment
In the last exercise of "Dual MapFragment", if the device orientation changed, the display area and zoom level will be kept, but the added marker will disappear.
In this exercise, we are going to modify map2 from last post, to retain instance after orientation changed.
To keep the markers after orientation changed, create custom MapFragment (RetainMapFragment), override onActivityCreated() call setRetainInstance(true).
Modify layout file to use "com.example.androidmapex.RetainMapFragment" class on map2.
Modify MainActivity to use define myMapFragment2 as RetainMapFragment.
Related:
- Retain data using Fragment API setRetainInstance()
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
In this exercise, we are going to modify map2 from last post, to retain instance after orientation changed.
To keep the markers after orientation changed, create custom MapFragment (RetainMapFragment), override onActivityCreated() call setRetainInstance(true).
package com.example.androidmapex;
import android.os.Bundle;
import com.google.android.gms.maps.MapFragment;
public class RetainMapFragment extends MapFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
}
}
Modify layout file to use "com.example.androidmapex.RetainMapFragment" class on map2.
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<fragment
android:id="@+id/map1"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="2"
android:layout_margin="5px"
class="com.google.android.gms.maps.MapFragment"/>
<fragment
android:id="@+id/map2"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="3"
android:layout_margin="5px"
class="com.example.androidmapex.RetainMapFragment"/>
</LinearLayout>
Modify MainActivity to use define myMapFragment2 as RetainMapFragment.
package com.example.androidmapex;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
public class MainActivity extends Activity{
private GoogleMap myMap1, myMap2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager myFragmentManager = getFragmentManager();
MapFragment myMapFragment1 =
(MapFragment)myFragmentManager.findFragmentById(R.id.map1);
RetainMapFragment myMapFragment2 =
(RetainMapFragment)myFragmentManager.findFragmentById(R.id.map2);
myMap1 = myMapFragment1.getMap();
myMap2 = myMapFragment2.getMap();
myMap1.setOnMapLongClickListener(my1_OnMapLongClickListener);
myMap2.setOnMapLongClickListener(my2_OnMapLongClickListener);
}
OnMapLongClickListener my1_OnMapLongClickListener =
new OnMapLongClickListener(){
@Override
public void onMapLongClick(LatLng point) {
myMap1.addMarker(new MarkerOptions()
.position(point)
.title(point.toString()));
}
};
OnMapLongClickListener my2_OnMapLongClickListener =
new OnMapLongClickListener(){
@Override
public void onMapLongClick(LatLng point) {
BitmapDescriptor bitmapDescriptor =
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE);
myMap2.addMarker(new MarkerOptions()
.position(point)
.icon(bitmapDescriptor)
.title(point.toString()));
}
};
}
Related:
- Retain data using Fragment API setRetainInstance()
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
Thursday, March 28, 2013
Dual MapFragment of Google Maps Android API v2
This exercise demonstrate how to embed two MapFragment in a Activity.
Modify layout file to have two fragment of "com.google.android.gms.maps.MapFragment".
Modify MainActivity.java to handle the Maps separately.
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
Modify layout file to have two fragment of "com.google.android.gms.maps.MapFragment".
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<fragment
android:id="@+id/map1"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="2"
android:layout_margin="5px"
class="com.google.android.gms.maps.MapFragment"/>
<fragment
android:id="@+id/map2"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="3"
android:layout_margin="5px"
class="com.google.android.gms.maps.MapFragment"/>
</LinearLayout>
Modify MainActivity.java to handle the Maps separately.
package com.example.androidmapex;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
public class MainActivity extends Activity{
private GoogleMap myMap1, myMap2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager myFragmentManager = getFragmentManager();
MapFragment myMapFragment1 =
(MapFragment)myFragmentManager.findFragmentById(R.id.map1);
MapFragment myMapFragment2 =
(MapFragment)myFragmentManager.findFragmentById(R.id.map2);
myMap1 = myMapFragment1.getMap();
myMap2 = myMapFragment2.getMap();
myMap1.setOnMapLongClickListener(my1_OnMapLongClickListener);
myMap2.setOnMapLongClickListener(my2_OnMapLongClickListener);
}
OnMapLongClickListener my1_OnMapLongClickListener =
new OnMapLongClickListener(){
@Override
public void onMapLongClick(LatLng point) {
myMap1.addMarker(new MarkerOptions()
.position(point)
.title(point.toString()));
}
};
OnMapLongClickListener my2_OnMapLongClickListener =
new OnMapLongClickListener(){
@Override
public void onMapLongClick(LatLng point) {
BitmapDescriptor bitmapDescriptor =
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE);
myMap2.addMarker(new MarkerOptions()
.position(point)
.icon(bitmapDescriptor)
.title(point.toString()));
}
};
}
Download the files.
The series:
A simple example using Google Maps Android API v2, step by step.
Google Maps Engine Lite (Beta) launched
Google is launching Google Maps Engine Lite (Beta) helping you create advanced custom maps to share with collaborators and also publish to the web. You can visualize and map more data, import locations from a spreadsheet, use layers to visualize different types of content, or simply draw and add places, lines, and shapes.
Visit: Log-in your google account and browse Google Maps Engine Lite
- Learn more about Maps Engine Lite (Beta)
Visit: Log-in your google account and browse Google Maps Engine Lite
Google Maps Engine Lite |
- Learn more about Maps Engine Lite (Beta)
Wednesday, March 27, 2013
Stop IntentService
I have numbers of post about IntentService before; include Perform background processing with IntentService, Share IntentService among Fragments, Send data from IntentService to Activity, via additional Broadcast and Generate Notification in IntentService. This post is a good exercise to understand the life-cycle of IntentService.
To stop a IntentService, call the method stopService (Intent service). It request that a given application service be stopped. If the service is not running, nothing happens. Otherwise it is stopped. Note that calls to startService() are not counted -- this stops the service no matter how many times it was started. So imple? not at all.
In this exercise, buttons are added to start and stop IntentService. It can be noted that:
Layout file
MainActivity.java
MyIntentService.java
Need to include <service> of "MyIntentService" in AndroidManifest.xml, refer to the post "Send data from IntentService to Activity, via additional Broadcast".
Download the files.
To stop a IntentService, call the method stopService (Intent service). It request that a given application service be stopped. If the service is not running, nothing happens. Otherwise it is stopped. Note that calls to startService() are not counted -- this stops the service no matter how many times it was started. So imple? not at all.
In this exercise, buttons are added to start and stop IntentService. It can be noted that:
- If you click the "Start IntentService" multi times, only one request will be processed at a time, All requests are handled on a single worker thread. The extra requests will be place in a queue.
- If you click the "Start IntentService" multi times, only ONE call of stopService() is need to stop all request.
- If you remove the checking on the boolean stopped, in onHandleIntent() of MyIntentService.java; call stopService() will call onDestroy() of MyIntentService, but the code in onHandleIntent() will keep running until finish by itself. Because onHandleIntent() is running on another worker thread.
Layout file
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start IntentService" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop IntentService" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:max="10"
android:progress="0"/>
</LinearLayout>
MainActivity.java
package com.example.androidintentservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
Button buttonStart, buttonStop;
TextView textResult;
ProgressBar progressBar;
private MyBroadcastReceiver myBroadcastReceiver;
private MyBroadcastReceiver_Update myBroadcastReceiver_Update;
Intent intentMyIntentService;
int numberOfIntentService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.result);
progressBar = (ProgressBar)findViewById(R.id.progressbar);
buttonStart = (Button)findViewById(R.id.start);
buttonStop = (Button)findViewById(R.id.stop);
buttonStart.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
numberOfIntentService++;
//prepare String passing to intentMyIntentService
String msgToIntentService = "Android-er: " + numberOfIntentService;
//Start MyIntentService
intentMyIntentService = new Intent(MainActivity.this, MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_IN, msgToIntentService);
startService(intentMyIntentService);
}});
buttonStop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
if(intentMyIntentService != null){
stopService(intentMyIntentService);
intentMyIntentService = null;
}
}});
numberOfIntentService = 0;
myBroadcastReceiver = new MyBroadcastReceiver();
myBroadcastReceiver_Update = new MyBroadcastReceiver_Update();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver, intentFilter);
IntentFilter intentFilter_update = new IntentFilter(MyIntentService.ACTION_MyUpdate);
intentFilter_update.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver_Update, intentFilter_update);
}
@Override
protected void onDestroy() {
super.onDestroy();
//un-register BroadcastReceiver
unregisterReceiver(myBroadcastReceiver);
unregisterReceiver(myBroadcastReceiver_Update);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra(MyIntentService.EXTRA_KEY_OUT);
textResult.setText(result);
}
}
public class MyBroadcastReceiver_Update extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int update = intent.getIntExtra(MyIntentService.EXTRA_KEY_UPDATE, 0);
progressBar.setProgress(update);
}
}
}
MyIntentService.java
package com.example.androidintentservice;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
public class MyIntentService extends IntentService {
private static final int MY_NOTIFICATION_ID=1;
private static final int MY_DESTORY_NOTIFICATION_ID=2;
NotificationManager notificationManager;
Notification myNotification;
public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String ACTION_MyUpdate = "com.example.androidintentservice.UPDATE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
public static final String EXTRA_KEY_UPDATE = "EXTRA_UPDATE";
String msgFromActivity;
String extraOut;
boolean success;
boolean stopped;
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
success = false;
stopped = false;
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
msgFromActivity = intent.getStringExtra(EXTRA_KEY_IN);
extraOut = "Hello: " + msgFromActivity;
//total 10 sec
for(int i = 0; i <=10; i++){
try {
Thread.sleep(1000); //every 1 sec
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//--- Try to comment it ---//
if(stopped){
break;
}
//send update
Intent intentUpdate = new Intent();
intentUpdate.setAction(ACTION_MyUpdate);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(EXTRA_KEY_UPDATE, i);
sendBroadcast(intentUpdate);
PendingIntent pendingIntent_doNothing = PendingIntent.getActivity(
getApplicationContext(),
0,
new Intent(), //empty Intent do nothing
Intent.FLAG_ACTIVITY_NEW_TASK);
//generate notification
String notificationText = String.valueOf((int)(100 * i / 10)) + " %";
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Progress")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent_doNothing)
.build();
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}
success = true;
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Success Finished")
.setContentText("Successful Finished")
.setTicker("Successful Finished")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}
@Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onDestroy() {
Notification onDestroyNotification;
String notice;
stopped = true;
if(success){
notice = "onDestroy with success";
onDestroyNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notice)
.setContentText(msgFromActivity)
.setTicker(notice)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
}else{
notice = "onDestroy WITHOUT success!";
onDestroyNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notice)
.setContentText(msgFromActivity)
.setTicker(notice)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
}
notificationManager.notify(MY_DESTORY_NOTIFICATION_ID, onDestroyNotification);
Toast.makeText(getApplicationContext(), notice, Toast.LENGTH_LONG).show();
super.onDestroy();
}
}
Need to include <service> of "MyIntentService" in AndroidManifest.xml, refer to the post "Send data from IntentService to Activity, via additional Broadcast".
Download the files.
Create a PendingIntent for Notification to do nothing
Refer to the last post "error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required", if you want no action perform when user click on the Notification, you can insert a PendingIntent with a dummy Intent.
Example:
Example:
PendingIntent pendingIntent = PendingIntent.getActivity(
MainActivity.this,
0,
new Intent(), //Dummy Intent do nothing
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification = new NotificationCompat.Builder(context)
.setContentTitle("Exercise of Notification!")
.setContentText("http://android-er.blogspot.com/")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required
Refer to the exercise "Example of using NotificationCompat.Builder"; if the statement of new NotificationCompat.Builder...build() modified to remove .setContentIntent(pendingIntent), error of java.lang.IllegalArgumentException: contentIntent required MAY be thrown.
It will have no error in compile time, and no error when run on HTC One X (Android 4.1.1) and HTC Fly (Android 3.2.1). But error when run on Nexus One (Android 2.3.6), with error:
03-27 21:33:40.631: D/AndroidRuntime(24248): Shutting down VM
03-27 21:33:40.631: W/dalvikvm(24248): threadid=1: thread exiting with uncaught exception (group=0x40015560)
03-27 21:33:40.651: E/AndroidRuntime(24248): FATAL EXCEPTION: main
03-27 21:33:40.651: E/AndroidRuntime(24248): java.lang.IllegalArgumentException: contentIntent required: pkg=com.example.androidnotificationbuilder id=1 notification=Notification(vibrate=null,sound=default,defaults=0x1,flags=0x10)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Parcel.readException(Parcel.java:1326)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Parcel.readException(Parcel.java:1276)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:274)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.NotificationManager.notify(NotificationManager.java:111)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.NotificationManager.notify(NotificationManager.java:91)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.example.androidnotificationbuilder.MainActivity$1.onClick(MainActivity.java:52)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.view.View.performClick(View.java:2485)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.view.View$PerformClick.run(View.java:9080)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Handler.handleCallback(Handler.java:587)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Handler.dispatchMessage(Handler.java:92)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Looper.loop(Looper.java:130)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.ActivityThread.main(ActivityThread.java:3683)
03-27 21:33:40.651: E/AndroidRuntime(24248): at java.lang.reflect.Method.invokeNative(Native Method)
03-27 21:33:40.651: E/AndroidRuntime(24248): at java.lang.reflect.Method.invoke(Method.java:507)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-27 21:33:40.651: E/AndroidRuntime(24248): at dalvik.system.NativeStart.main(Native Method)
If you want no action perform when user click on the Notification, you can create a PendingIntent with empty Intent for Notification to do nothing.
It will have no error in compile time, and no error when run on HTC One X (Android 4.1.1) and HTC Fly (Android 3.2.1). But error when run on Nexus One (Android 2.3.6), with error:
03-27 21:33:40.631: D/AndroidRuntime(24248): Shutting down VM
03-27 21:33:40.631: W/dalvikvm(24248): threadid=1: thread exiting with uncaught exception (group=0x40015560)
03-27 21:33:40.651: E/AndroidRuntime(24248): FATAL EXCEPTION: main
03-27 21:33:40.651: E/AndroidRuntime(24248): java.lang.IllegalArgumentException: contentIntent required: pkg=com.example.androidnotificationbuilder id=1 notification=Notification(vibrate=null,sound=default,defaults=0x1,flags=0x10)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Parcel.readException(Parcel.java:1326)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Parcel.readException(Parcel.java:1276)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:274)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.NotificationManager.notify(NotificationManager.java:111)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.NotificationManager.notify(NotificationManager.java:91)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.example.androidnotificationbuilder.MainActivity$1.onClick(MainActivity.java:52)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.view.View.performClick(View.java:2485)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.view.View$PerformClick.run(View.java:9080)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Handler.handleCallback(Handler.java:587)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Handler.dispatchMessage(Handler.java:92)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.os.Looper.loop(Looper.java:130)
03-27 21:33:40.651: E/AndroidRuntime(24248): at android.app.ActivityThread.main(ActivityThread.java:3683)
03-27 21:33:40.651: E/AndroidRuntime(24248): at java.lang.reflect.Method.invokeNative(Native Method)
03-27 21:33:40.651: E/AndroidRuntime(24248): at java.lang.reflect.Method.invoke(Method.java:507)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-27 21:33:40.651: E/AndroidRuntime(24248): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-27 21:33:40.651: E/AndroidRuntime(24248): at dalvik.system.NativeStart.main(Native Method)
If you want no action perform when user click on the Notification, you can create a PendingIntent with empty Intent for Notification to do nothing.
Tuesday, March 26, 2013
Generate Notification in IntentService
Last exercise demonstrate how to "Send data from IntentService to Activity, via additional Broadcast". We can also generate Notification in IntentService, to inform user about the progress.
Modify MyIntentService.java from last exercise.
Download the files.
Related:
- error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required
Next:
- Stop IntentService, and know about the life-cycle of IntentService.
Modify MyIntentService.java from last exercise.
package com.example.androidintentservice;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
public class MyIntentService extends IntentService {
private static final int MY_NOTIFICATION_ID=1;
NotificationManager notificationManager;
Notification myNotification;
public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String ACTION_MyUpdate = "com.example.androidintentservice.UPDATE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
public static final String EXTRA_KEY_UPDATE = "EXTRA_UPDATE";
String msgFromActivity;
String extraOut;
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
msgFromActivity = intent.getStringExtra(EXTRA_KEY_IN);
extraOut = "Hello: " + msgFromActivity;
for(int i = 0; i <=10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//send update
Intent intentUpdate = new Intent();
intentUpdate.setAction(ACTION_MyUpdate);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(EXTRA_KEY_UPDATE, i);
sendBroadcast(intentUpdate);
//generate notification
String notificationText = String.valueOf((int)(100 * i / 10)) + " %";
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Progress")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}
}
Download the files.
Related:
- error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required
Next:
- Stop IntentService, and know about the life-cycle of IntentService.
Monday, March 25, 2013
Send data from IntentService to Activity, via additional Broadcast
The former post demonstrate "Perform background processing with IntentService". It's a standard approach for IntentService, inform the Activity end of job by sending a Broadcast with Extra of respond.
But how can main Activity know the status of IntentService before end of job? It's another exercise to send additional Broadcast with another IntentFilter while running, to update main Activity, from IntentService. Such that we can implement additional BroadcastReceiver in main Activity to receive the additional Broadcast , and then update a ProgressBar.
MyIntentService.java
MainActivity.java
activity_main.xml
Need to include <service> of "MyIntentService" in AndroidManifest.xml
Download the files.
Related:
- Generate Notification in IntentService
But how can main Activity know the status of IntentService before end of job? It's another exercise to send additional Broadcast with another IntentFilter while running, to update main Activity, from IntentService. Such that we can implement additional BroadcastReceiver in main Activity to receive the additional Broadcast , and then update a ProgressBar.
MyIntentService.java
package com.example.androidintentservice;
import android.app.IntentService;
import android.content.Intent;
public class MyIntentService extends IntentService {
public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String ACTION_MyUpdate = "com.example.androidintentservice.UPDATE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
public static final String EXTRA_KEY_UPDATE = "EXTRA_UPDATE";
String msgFromActivity;
String extraOut;
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
msgFromActivity = intent.getStringExtra(EXTRA_KEY_IN);
extraOut = "Hello: " + msgFromActivity;
for(int i = 0; i <=10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//send update
Intent intentUpdate = new Intent();
intentUpdate.setAction(ACTION_MyUpdate);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(EXTRA_KEY_UPDATE, i);
sendBroadcast(intentUpdate);
}
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}
}
MainActivity.java
package com.example.androidintentservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textResult;
ProgressBar progressBar;
private MyBroadcastReceiver myBroadcastReceiver;
private MyBroadcastReceiver_Update myBroadcastReceiver_Update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.result);
progressBar = (ProgressBar)findViewById(R.id.progressbar);
//prepare MyParcelable passing to intentMyIntentService
String msgToIntentService = "Android-er";
//Start MyIntentService
Intent intentMyIntentService = new Intent(this, MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_IN, msgToIntentService);
startService(intentMyIntentService);
myBroadcastReceiver = new MyBroadcastReceiver();
myBroadcastReceiver_Update = new MyBroadcastReceiver_Update();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver, intentFilter);
IntentFilter intentFilter_update = new IntentFilter(MyIntentService.ACTION_MyUpdate);
intentFilter_update.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver_Update, intentFilter_update);
}
@Override
protected void onDestroy() {
super.onDestroy();
//un-register BroadcastReceiver
unregisterReceiver(myBroadcastReceiver);
unregisterReceiver(myBroadcastReceiver_Update);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra(MyIntentService.EXTRA_KEY_OUT);
textResult.setText(result);
}
}
public class MyBroadcastReceiver_Update extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int update = intent.getIntExtra(MyIntentService.EXTRA_KEY_UPDATE, 0);
progressBar.setProgress(update);
}
}
}
activity_main.xml
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:max="10"
android:progress="0"/>
</LinearLayout>
Need to include <service> of "MyIntentService" in AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidintentservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidintentservice.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>
<service android:name="com.example.androidintentservice.MyIntentService"></service>
</application>
</manifest>
Download the files.
Related:
- Generate Notification in IntentService
Example of using NotificationCompat.Builder
Last exercise demonstrate "Notification.Builder". If your app supports versions of Android as old as API level 4, you can instead use NotificationCompat.Builder, available in the Android Support library.
Simple replace Notification.Builder with NotificationCompat.Builder, and import android.support.v4.app.NotificationCompat.
Related:
- error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required
Simple replace Notification.Builder with NotificationCompat.Builder, and import android.support.v4.app.NotificationCompat.
myNotification = new NotificationCompat.Builder(context)
.setContentTitle("Exercise of Notification!")
.setContentText("http://android-er.blogspot.com/")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
Related:
- error of using NotificationCompat.Builder, IllegalArgumentException: contentIntent required
Example of using Notification.Builder
android.app.Notification.Builder is a builder class for Notification objects. Provides a convenient way to set the various fields of a Notification and generate content views using the platform's notification layout template. If your app supports versions of Android as old as API level 4, you can instead use NotificationCompat.Builder, available in the Android Support library.
Note: minSdkVersion have to be set ="16".
package com.example.androidnotificationbuilder;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private static final int MY_NOTIFICATION_ID=1;
NotificationManager notificationManager;
Notification myNotification;
private final String myBlog = "http://android-er.blogspot.com/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonSend = (Button)findViewById(R.id.send);
buttonSend.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
Context context = getApplicationContext();
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent = PendingIntent.getActivity(
MainActivity.this,
0,
myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification = new Notification.Builder(context)
.setContentTitle("Exercise of Notification!")
.setContentText("http://android-er.blogspot.com/")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}});
}
}
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/send"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send a Notification" />
</LinearLayout>
Note: minSdkVersion have to be set ="16".
Friday, March 22, 2013
Share IntentService among Fragments
The post "Perform background processing with IntentService" demonstrate how to use IntentService in Activity. In this exercise, we are going to modify the exercise of "Yahoo Weather" to demonstrate how to share one IntentService by three Fragments. Here one IntentService means one common IntentService class, not one common IntentService object.
Create MyIntentService.java, it's our common IntentService class, to load Yahoo Weather in background service.
Modify AndroidManifest.xml to add <service> of "MyIntentService", and add permission of "android.permission.INTERNET".
res/layout/fragmentlayout.xml, layout of our fragments.
Creater a abstract class MyAbsYWeatherFragment extends Fragment, all our fragments will extend it. All it's sub-class have to override init_country() method to provide the target city of Yahoo Weather, a string of ACTION_RESPONSE for IntentFilter, and boolean retainInst to determine is it need retain instance. It will start our IntentService and handle all job for our fragments.
Create three sub-class of MyAbsYWeatherFragment, Fragment1, Fragment2 and Fragment3. They are the actual fragments in the layout.
Fragment1.java
Fragment2.java
Fragment3.java
Modify /res/layout/activity_main.xml and /res/layout-land/activity_main.xml to add the three fragments in normal and landscape orientation.
/res/layout/activity_main.xml
/res/layout-land/activity_main.xml
MainActivity
- Fragment1 call setRetainInstance(flase), so everytime orientation changed, it will re-start and reload new weather.
- Fragment3 call setRetainInstance(true), so it will not reload weather.
- Fragment2 call setRetainInstance(true), it will not reload weather too. But it have the same Action string for IntentFilter of Fragment1, so when IntentService of Fragment1 finished, BroadcastReceiver of Fragment2 will be called also.
Download the files.
If you have RuntimeException: Unable to instantiate activity ComponentInfo, please read HERE.
Create MyIntentService.java, it's our common IntentService class, to load Yahoo Weather in background service.
package com.example.androidyahooweatherdom;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.app.IntentService;
import android.content.Intent;
public class MyIntentService extends IntentService {
String ExtraAction;
String woeid;
MyWeather weatherResult;
public static final String EXTRA_KEY_ACTION = "EXTRA_ACTION";
public static final String EXTRA_KEY_WOEID = "EXTRA_WOEID";
public static final String EXTRA_KEY_WEATHER = "EXTRA_WEATHER";
class MyWeather{
String description;
String city;
String region;
String country;
String windChill;
String windDirection;
String windSpeed;
String sunrise;
String sunset;
String conditiontext;
String conditiondate;
String numberOfForecast;
String forecast;
public String toString(){
return "\n- " + description + " -\n\n"
+ "city: " + city + "\n"
+ "region: " + region + "\n"
+ "country: " + country + "\n\n"
+ "Wind\n"
+ "chill: " + windChill + "\n"
+ "direction: " + windDirection + "\n"
+ "speed: " + windSpeed + "\n\n"
+ "Sunrise: " + sunrise + "\n"
+ "Sunset: " + sunset + "\n\n"
+ "Condition: " + conditiontext + "\n"
+ conditiondate +"\n"
+ "\n"
+ "number of forecast: " + numberOfForecast + "\n"
+ forecast;
}
}
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
ExtraAction = intent.getStringExtra(EXTRA_KEY_ACTION);
woeid = intent.getStringExtra(EXTRA_KEY_WOEID);
loadYahooWeather();
//dummy delay
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ExtraAction);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_WEATHER, weatherResult.toString());
sendBroadcast(intentResponse);
}
protected void loadYahooWeather(){
String weatherString = QueryYahooWeather();
Document weatherDoc = convertStringToDocument(weatherString);
weatherResult = parseWeather(weatherDoc);
}
private MyWeather parseWeather(Document srcDoc){
MyWeather myWeather = new MyWeather();
//<description>Yahoo! Weather for New York, NY</description>
myWeather.description = srcDoc.getElementsByTagName("description")
.item(0)
.getTextContent();
//<yweather:location.../>
Node locationNode = srcDoc.getElementsByTagName("yweather:location").item(0);
myWeather.city = locationNode.getAttributes()
.getNamedItem("city")
.getNodeValue()
.toString();
myWeather.region = locationNode.getAttributes()
.getNamedItem("region")
.getNodeValue()
.toString();
myWeather.country = locationNode.getAttributes()
.getNamedItem("country")
.getNodeValue()
.toString();
//<yweather:wind.../>
Node windNode = srcDoc.getElementsByTagName("yweather:wind").item(0);
myWeather.windChill = windNode.getAttributes()
.getNamedItem("chill")
.getNodeValue()
.toString();
myWeather.windDirection = windNode.getAttributes()
.getNamedItem("direction")
.getNodeValue()
.toString();
myWeather.windSpeed = windNode.getAttributes()
.getNamedItem("speed")
.getNodeValue()
.toString();
//<yweather:astronomy.../>
Node astronomyNode = srcDoc.getElementsByTagName("yweather:astronomy").item(0);
myWeather.sunrise = astronomyNode.getAttributes()
.getNamedItem("sunrise")
.getNodeValue()
.toString();
myWeather.sunset = astronomyNode.getAttributes()
.getNamedItem("sunset")
.getNodeValue()
.toString();
//<yweather:condition.../>
Node conditionNode = srcDoc.getElementsByTagName("yweather:condition").item(0);
myWeather.conditiontext = conditionNode.getAttributes()
.getNamedItem("text")
.getNodeValue()
.toString();
myWeather.conditiondate = conditionNode.getAttributes()
.getNamedItem("date")
.getNodeValue()
.toString();
//Added to get elements of <yweather:forecast.../>
NodeList forecastList = srcDoc.getElementsByTagName("yweather:forecast");
myWeather.forecast = "";
if(forecastList.getLength() > 0){
myWeather.numberOfForecast = String.valueOf(forecastList.getLength());
for(int i = 0; i < forecastList.getLength(); i++){
Node forecastNode = forecastList.item(i);
myWeather.forecast +=
forecastNode
.getAttributes()
.getNamedItem("date")
.getNodeValue()
.toString() + " " +
forecastNode
.getAttributes()
.getNamedItem("text")
.getNodeValue()
.toString() +
" High: " + forecastNode
.getAttributes()
.getNamedItem("high")
.getNodeValue()
.toString() +
" Low: " + forecastNode
.getAttributes()
.getNamedItem("low")
.getNodeValue()
.toString() + "\n";
}
}else{
myWeather.numberOfForecast = "No forecast";
}
return myWeather;
}
private Document convertStringToDocument(String src){
Document dest = null;
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder parser;
try {
parser = dbFactory.newDocumentBuilder();
dest = parser.parse(new ByteArrayInputStream(src.getBytes()));
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return dest;
}
private String QueryYahooWeather(){
String qResult = "";
String queryString = "http://weather.yahooapis.com/forecastrss?w=" + woeid;
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(queryString);
try {
HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
if (httpEntity != null){
InputStream inputStream = httpEntity.getContent();
Reader in = new InputStreamReader(inputStream);
BufferedReader bufferedreader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String stringReadLine = null;
while ((stringReadLine = bufferedreader.readLine()) != null) {
stringBuilder.append(stringReadLine + "\n");
}
qResult = stringBuilder.toString();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return qResult;
}
}
Modify AndroidManifest.xml to add <service> of "MyIntentService", and add permission of "android.permission.INTERNET".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidyahooweatherdom"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<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="com.example.androidyahooweatherdom.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>
<service android:name="MyIntentService"></service>
</application>
</manifest>
res/layout/fragmentlayout.xml, layout of our fragments.
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/weather"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
Creater a abstract class MyAbsYWeatherFragment extends Fragment, all our fragments will extend it. All it's sub-class have to override init_country() method to provide the target city of Yahoo Weather, a string of ACTION_RESPONSE for IntentFilter, and boolean retainInst to determine is it need retain instance. It will start our IntentService and handle all job for our fragments.
package com.example.androidyahooweatherdom;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public abstract class MyAbsYWeatherFragment extends Fragment {
TextView weather, status;
String stringWeatherResult;
private MyBroadcastReceiver myBroadcastReceiver;
String woeid;
String ACTION_RESPONSE;
boolean retainInst;
abstract void init_country();
public MyAbsYWeatherFragment(){
super();
init_country();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.fragmentlayout, container, false);
weather = (TextView)myFragmentView.findViewById(R.id.weather);
status = (TextView)myFragmentView.findViewById(R.id.status);
myBroadcastReceiver = new MyBroadcastReceiver();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(ACTION_RESPONSE);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
getActivity().registerReceiver(myBroadcastReceiver, intentFilter);
return myFragmentView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
if(stringWeatherResult != null){
weather.setText(stringWeatherResult);
status.setText("Reloaded previous weatherResult");
}else{
status.setText("loadYahooWeather()");
startServiceToLoadYahooWeather();
}
setRetainInstance(retainInst);
}
@Override
public void onDestroyView() {
// TODO Auto-generated method stub
super.onDestroyView();
//un-register BroadcastReceiver
getActivity().unregisterReceiver(myBroadcastReceiver);
}
protected void startServiceToLoadYahooWeather(){
Intent intentMyIntentService = new Intent(getActivity().getApplicationContext(), MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_ACTION, ACTION_RESPONSE);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_WOEID, woeid);
getActivity().startService(intentMyIntentService);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
stringWeatherResult = intent.getStringExtra(MyIntentService.EXTRA_KEY_WEATHER);
FragmentActivity parentActivity = getActivity();
if(parentActivity != null){
parentActivity.runOnUiThread(new Runnable(){
@Override
public void run() {
weather.setText(stringWeatherResult);
status.setText("Finished");
}});
}
}
}
}
Create three sub-class of MyAbsYWeatherFragment, Fragment1, Fragment2 and Fragment3. They are the actual fragments in the layout.
Fragment1.java
package com.example.androidyahooweatherdom;
public class Fragment1 extends MyAbsYWeatherFragment {
@Override
void init_country() {
//New York
woeid = "2459115";
ACTION_RESPONSE = "androidyahooweatherdom.RESPONSE.NewYork";
retainInst = false;
}
}
Fragment2.java
package com.example.androidyahooweatherdom;
public class Fragment2 extends MyAbsYWeatherFragment {
@Override
void init_country() {
//New York
woeid = "2459115";
ACTION_RESPONSE = "androidyahooweatherdom.RESPONSE.NewYork";
retainInst = true;
}
}
Fragment3.java
package com.example.androidyahooweatherdom;
public class Fragment3 extends MyAbsYWeatherFragment {
@Override
void init_country() {
//London
woeid = "23416974";
ACTION_RESPONSE = "androidyahooweatherdom.RESPONSE.London";
retainInst = true;
}
}
Modify /res/layout/activity_main.xml and /res/layout-land/activity_main.xml to add the three fragments in normal and landscape orientation.
/res/layout/activity_main.xml
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >
<fragment
class="com.example.androidyahooweatherdom.Fragment1"
android:id="@+id/fragment1"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
<fragment
class="com.example.androidyahooweatherdom.Fragment2"
android:id="@+id/fragment2"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
<fragment
class="com.example.androidyahooweatherdom.Fragment3"
android:id="@+id/fragment3"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
/res/layout-land/activity_main.xml
<LinearLayout 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:orientation="horizontal"
tools:context=".MainActivity" >
<fragment
class="com.example.androidyahooweatherdom.Fragment1"
android:id="@+id/fragment1"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
class="com.example.androidyahooweatherdom.Fragment2"
android:id="@+id/fragment2"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
class="com.example.androidyahooweatherdom.Fragment3"
android:id="@+id/fragment3"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
MainActivity
package com.example.androidyahooweatherdom;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
- Fragment1 call setRetainInstance(flase), so everytime orientation changed, it will re-start and reload new weather.
- Fragment3 call setRetainInstance(true), so it will not reload weather.
- Fragment2 call setRetainInstance(true), it will not reload weather too. But it have the same Action string for IntentFilter of Fragment1, so when IntentService of Fragment1 finished, BroadcastReceiver of Fragment2 will be called also.
Download the files.
If you have RuntimeException: Unable to instantiate activity ComponentInfo, please read HERE.
Thursday, March 21, 2013
Example to implement Parcelable
Parcel is a class container for a message (data and object references) that can be sent through an IBinder. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC (using the various methods here for writing specific types, or the general Parcelable interface), and references to live IBinder objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel.
Parcelable is Interface for classes whose instances can be written to and restored from a Parcel. Classes implementing the Parcelable interface must also have a static field called CREATOR, which is an object implementing the Parcelable.Creator interface.
Modify last exercise "Perform background processing with IntentService" to pass extra as our custom Parcelable.
Create our custom class MyParcelable.java, implements Parcelable.
Modify main activity, MainActivity.java to pass Extra as MyParcelable.
Modify MyIntentService.java to receive MyIntentService.
Download the files.
Parcelable is Interface for classes whose instances can be written to and restored from a Parcel. Classes implementing the Parcelable interface must also have a static field called CREATOR, which is an object implementing the Parcelable.Creator interface.
Modify last exercise "Perform background processing with IntentService" to pass extra as our custom Parcelable.
Create our custom class MyParcelable.java, implements Parcelable.
package com.example.androidintentservice;
import android.os.Parcel;
import android.os.Parcelable;
public class MyParcelable implements Parcelable {
public String blogName;
public String blogAddress;
public static final Parcelable.Creator<MyParcelable> CREATOR =
new Parcelable.Creator<MyParcelable>(){
@Override
public MyParcelable createFromParcel(Parcel source) {
return new MyParcelable(source);
}
@Override
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
public MyParcelable(){
}
public MyParcelable(Parcel source){
readFromParcel(source);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(blogName);
dest.writeString(blogAddress);
}
public void readFromParcel(Parcel source){
blogName = source.readString();
blogAddress = source.readString();
}
}
Modify main activity, MainActivity.java to pass Extra as MyParcelable.
package com.example.androidintentservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textResult;
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.result);
//prepare MyParcelable passing to intentMyIntentService
MyParcelable myParcelable = new MyParcelable();
myParcelable.blogName = "Android-er";
myParcelable.blogAddress = "http://android-er.blogspot.com/";
//Start MyIntentService
Intent intentMyIntentService = new Intent(this, MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_IN, myParcelable);
startService(intentMyIntentService);
myBroadcastReceiver = new MyBroadcastReceiver();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//un-register BroadcastReceiver
unregisterReceiver(myBroadcastReceiver);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra(MyIntentService.EXTRA_KEY_OUT);
textResult.setText(result);
}
}
}
Modify MyIntentService.java to receive MyIntentService.
package com.example.androidintentservice;
import android.app.IntentService;
import android.content.Intent;
public class MyIntentService extends IntentService {
public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
MyParcelable parcelableIn;
String extraOut;
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
parcelableIn = intent.getParcelableExtra(EXTRA_KEY_IN);
extraOut = "Passed as Parcelable:\n"
+ parcelableIn.blogName + "\n"
+ parcelableIn.blogAddress;
//dummy delay for 5 sec
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //wait 3 sec
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}
}
Download the files.
Perform background processing with IntentService
android.app.IntentService is a subclass of android.app.Service that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Create our custom IntentService, MyIntentService.java
You have to implement constructor of MyIntentService(). If you only override the default constructor of MyIntentService(String name) from IntentService, RuntimeException of java.lang.InstantiationException with Unable to instantiate service will be thrown.
Modify layout to add a TextView to display result
Main code in MainActivity.java. In order to receive result from IntentService, implement BroadcastReceiver, register in onCreate() and unregister in onDestroy(). To start MyIntentService, call startService() with coresponding intent.
Modify AndroidManifest.xml to add <service> of MyIntentService
Download the files.
Next:
- Share IntentService among Fragments
- Send data from IntentService to Activity, via additional Broadcast
- Generate Notification in IntentService
Create our custom IntentService, MyIntentService.java
You have to implement constructor of MyIntentService(). If you only override the default constructor of MyIntentService(String name) from IntentService, RuntimeException of java.lang.InstantiationException with Unable to instantiate service will be thrown.
package com.example.androidintentservice;
import android.app.IntentService;
import android.content.Intent;
public class MyIntentService extends IntentService {
public static final String ACTION_MyIntentService = "com.example.androidintentservice.RESPONSE";
public static final String EXTRA_KEY_IN = "EXTRA_IN";
public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
String extraIn;
String extraOut;
public MyIntentService() {
super("com.example.androidintentservice.MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//get input
extraIn = intent.getStringExtra(EXTRA_KEY_IN);
extraOut = "Result from MyIntentService: Hello " + extraIn;
//dummy delay for 5 sec
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //wait 3 sec
//return result
Intent intentResponse = new Intent();
intentResponse.setAction(ACTION_MyIntentService);
intentResponse.addCategory(Intent.CATEGORY_DEFAULT);
intentResponse.putExtra(EXTRA_KEY_OUT, extraOut);
sendBroadcast(intentResponse);
}
}
Modify layout to add a TextView to display result
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Main code in MainActivity.java. In order to receive result from IntentService, implement BroadcastReceiver, register in onCreate() and unregister in onDestroy(). To start MyIntentService, call startService() with coresponding intent.
package com.example.androidintentservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textResult;
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.result);
//Start MyIntentService
Intent intentMyIntentService = new Intent(this, MyIntentService.class);
intentMyIntentService.putExtra(MyIntentService.EXTRA_KEY_IN, "Android-er");
startService(intentMyIntentService);
myBroadcastReceiver = new MyBroadcastReceiver();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(myBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//un-register BroadcastReceiver
unregisterReceiver(myBroadcastReceiver);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra(MyIntentService.EXTRA_KEY_OUT);
textResult.setText(result);
}
}
}
Modify AndroidManifest.xml to add <service> of MyIntentService
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidintentservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidintentservice.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>
<service android:name="com.example.androidintentservice.MyIntentService"></service>
</application>
</manifest>
Download the files.
Next:
- Share IntentService among Fragments
- Send data from IntentService to Activity, via additional Broadcast
- Generate Notification in IntentService