Android 使用messenger下载图像的绑定服务
我无法在boundservice中使用messenger下载图像,即使在android清单中显示单独进程中的服务Android 使用messenger下载图像的绑定服务,android,Android,我无法在boundservice中使用messenger下载图像,即使在android清单中显示单独进程中的服务 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="edu.vuum.mocca" android:versionCode="1" android:version
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.vuum.mocca"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<supports-screens android:smallScreens="false" android:xlargeScreens="true" android:normalScreens="true" android:largeScreens="true"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:uiOptions="splitActionBarWhenNarrow">
<activity
android:name="edu.vuum.mocca.DownloadActivity"
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="edu.vuum.mocca.DownloadService" android:process=":my_process"/>
</application>
</manifest>
downloadactivity downloadimage方法,当用户单击downloadimage按钮以使用DownloadService下载图像时调用
package edu.vuum.mocca;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
/**
* @class DownloadActivity
*
* @brief A class that allows a user to download a bitmap image using
* a DownloadService.
*/
public class DownloadActivity extends Activity {
/**
* Used for debugging.
*/
private final String TAG = getClass().getName();
private final static int LOG_OP = 1;
private final static String MESSAGE_URL = "course.examples.Services.Logging.MESSAGE";
private boolean mIsBound;
/**
* User's selection of URL to download
*/
private EditText mUrlEditText;
/**
* Image that's been downloaded
*/
private ImageView mImageView;
/**
* Default URL.
*/
private String mDefaultUrl =
"http://www.dre.vanderbilt.edu/~schmidt/ka.png";
/**
* Display progress of download
*/
private ProgressDialog mProgressDialog;
/**
* Reference to the Messenger that's implemented in the
* UniqueIDGeneratorService.
*/
private Messenger mMessengerRef = null;
/**
* This ServiceConnection is used to receive a Messenger proxy
* after binding to the UniqueIDGeneratorService using bindService().
*/
private ServiceConnection mConnection = new ServiceConnection() {
/**
* Called after the UniqueIDGeneratorService is connected to
* convey the result returned from onBind().
*/
public void onServiceConnected(ComponentName className,
IBinder messenger) {
//Log.d(TAG, "ComponentName:" + className);
// Create a newq Messenger that encapsulates the
// returned IBinder object and store it for later use
// in mMessengerRef.
mMessengerRef = new Messenger(messenger);
mIsBound = true;
}
/**
* Called if the Service crashes and is no longer
* available. The ServiceConnection will remain bound,
* but the service will not respond to any requests.
*/
public void onServiceDisconnected(ComponentName className) {
mMessengerRef = null;
mIsBound = false;
}
};
/**
* Method that initializes the Activity when it is first created.
*
* @param savedInstanceState
* Activity's previously frozen state, if there was one.
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Sets the content view specified in the main.xml file.
*/
setContentView(R.layout.main);
/**
* Caches references to the EditText and ImageView objects in
* data members to optimize subsequent access.
*/
mUrlEditText = (EditText) findViewById(R.id.mUrlEditText);
mImageView = (ImageView) findViewById(R.id.mImageView);
}
/**
* Show a toast, notifying a user of an error when retrieving a
* bitmap.
*/
void showErrorToast(String errorString) {
Toast.makeText(this,
errorString,
Toast.LENGTH_LONG).show();
}
/**
* Display a downloaded bitmap image if it's non-null; otherwise,
* it reports an error via a Toast.
*
* @param image
* The bitmap image
*/
void displayImage(Bitmap image)
{
if (mImageView == null)
showErrorToast("Problem with Application,"
+ " please contact the Developer.");
else if (image != null)
mImageView.setImageBitmap(image);
else
showErrorToast("image is corrupted,"
+ " please check the requested URL.");
}
/**
* Called when a user clicks a button to reset an image to
* default.
*
* @param view
* The "Reset Image" button
*/
public void resetImage(View view) {
mImageView.setImageResource(R.drawable.default_image);
}
/**
* Called when a user clicks the Download Image button to download
* an image using the DownloadService
*
* @param view
* The "Download Image" button
*/
public void downloadImage(View view) {
// Obtain the requested URL from the user input.
if (mIsBound) {
String url = getUrlString();
Log.e(DownloadActivity.class.getSimpleName(),
"Downloading " + url);
hideKeyboard();
// Inform the user that the download is starting.
showDialog("downloading via startService()");
// Create a request Message that indicates the Service should
// send the reply back to ReplyHandler encapsulated by the
// Messenger.
Message msg = Message.obtain(null, LOG_OP);
Bundle bundle = new Bundle();
bundle.putString(MESSAGE_URL, url);
msg.setData(bundle);
// Message request = Message.obtain();
msg.replyTo = new Messenger(new DownloadHandler(this));
try {
if (mMessengerRef != null) {
Log.d(TAG, "sending message to service with url");
// Send the request Message to the
// UniqueIDGeneratorService.
mMessengerRef.send(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
// Create an Intent to download an image in the background via
// a Service. The downloaded image is later diplayed in the
// UI Thread via the downloadHandler() method defined below.
// DownloadService.makeIntent(this, Uri.parse( getUrlString()));
}else{
Log.d(TAG, "service is not bounded restat again");
}
}
/**
* Hook method called by Android when this Activity becomes
* visible.
*/
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart()");
Log.d(TAG, "calling bindService()");
if (mMessengerRef == null)
// Bind to the UniqueIDGeneratorService associated with this
// Intent.
bindService(DownloadService.makeIntent(this),
this.mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mIsBound)
unbindService(mConnection);
}
/**
* @class DownloadHandler
*
* @brief An inner class that inherits from Handler and uses its
* handleMessage() hook method to process Messages sent to
* it from the DownloadService.
*/
private static class DownloadHandler extends Handler {
/**
* Allows Activity to be garbage collected properly.
*/
private WeakReference<DownloadActivity> mActivity;
/**
* Class constructor constructs mActivity as weak reference
* to the activity
*
* @param activity
* The corresponding activity
*/
public DownloadHandler(DownloadActivity activity) {
mActivity = new WeakReference<DownloadActivity>(activity);
}
/**
/**
* This hook method is dispatched in response to receiving
* the pathname back from the DownloadService.
*/
public void handleMessage(Message msg) {
DownloadActivity activity = mActivity.get();
// Bail out of the DownloadActivity is gone.
if (activity == null)
return;
// Extract the data from Message, which is in the form
// of a Bundle that can be passed across processes.
Bundle data = msg.getData();
// Extract the pathname from the Bundle.
String pathname = data.getString("PATHNAME");
// See if things worked or not.
if (msg.arg1 != RESULT_OK || pathname == null)
activity.showDialog("failed download");
// Stop displaying the progress dialog.
activity.dismissDialog();
// Display the image in the UI Thread.
activity.displayImage(BitmapFactory.decodeFile(pathname));
}
};
/**
* Display the Dialog to the User.
*
* @param message
* The String to display what download method was used.
*/
public void showDialog(String message) {
mProgressDialog =
ProgressDialog.show(this,
"Download",
message,
true);
}
/**
* Dismiss the Dialog
*/
public void dismissDialog() {
if (mProgressDialog != null)
mProgressDialog.dismiss();
}
/**
* Hide the keyboard after a user has finished typing the url.
*/
private void hideKeyboard() {
InputMethodManager mgr =
(InputMethodManager) getSystemService
(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(mUrlEditText.getWindowToken(),
0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.download, menu);
return true;
}
/**
* Read the URL EditText and return the String it contains.
*
* @return String value in mUrlEditText
*/
String getUrlString() {
String s = mUrlEditText.getText().toString();
if (s.equals(""))
s = mDefaultUrl;
return s;
}
}
使用messenger绑定服务,如果它在单独的进程中运行,则不需要单独的线程来执行长时间运行的任务
我需要知道为什么这个下载图像的服务不工作,即使它在单独的进程中运行
感谢您的帮助。由于存在NetworkMainThreadException,解决方案是将网络代码放入异步任务或线程中。如果可能,请将问题缩小到您的问题,它似乎太长了。我想使用boundservice meseenger进行长时间运行的过程下载图像。我的问题是,为什么我的HandleMessage服务在单独的过程中运行时没有加载图像,尽管服务给出了错误android.os.NetworkOnMainThreadException作为网络代码,请解释一下。或者,只有一个选项可以执行长时间运行的任务,因为backgroundthreadNetwork代码是当您的应用程序连接到internet或LAN上的服务器并使用流发送或接收数据时执行的所有代码。
package edu.vuum.mocca;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
/**
* @class DownloadActivity
*
* @brief A class that allows a user to download a bitmap image using
* a DownloadService.
*/
public class DownloadActivity extends Activity {
/**
* Used for debugging.
*/
private final String TAG = getClass().getName();
private final static int LOG_OP = 1;
private final static String MESSAGE_URL = "course.examples.Services.Logging.MESSAGE";
private boolean mIsBound;
/**
* User's selection of URL to download
*/
private EditText mUrlEditText;
/**
* Image that's been downloaded
*/
private ImageView mImageView;
/**
* Default URL.
*/
private String mDefaultUrl =
"http://www.dre.vanderbilt.edu/~schmidt/ka.png";
/**
* Display progress of download
*/
private ProgressDialog mProgressDialog;
/**
* Reference to the Messenger that's implemented in the
* UniqueIDGeneratorService.
*/
private Messenger mMessengerRef = null;
/**
* This ServiceConnection is used to receive a Messenger proxy
* after binding to the UniqueIDGeneratorService using bindService().
*/
private ServiceConnection mConnection = new ServiceConnection() {
/**
* Called after the UniqueIDGeneratorService is connected to
* convey the result returned from onBind().
*/
public void onServiceConnected(ComponentName className,
IBinder messenger) {
//Log.d(TAG, "ComponentName:" + className);
// Create a newq Messenger that encapsulates the
// returned IBinder object and store it for later use
// in mMessengerRef.
mMessengerRef = new Messenger(messenger);
mIsBound = true;
}
/**
* Called if the Service crashes and is no longer
* available. The ServiceConnection will remain bound,
* but the service will not respond to any requests.
*/
public void onServiceDisconnected(ComponentName className) {
mMessengerRef = null;
mIsBound = false;
}
};
/**
* Method that initializes the Activity when it is first created.
*
* @param savedInstanceState
* Activity's previously frozen state, if there was one.
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Sets the content view specified in the main.xml file.
*/
setContentView(R.layout.main);
/**
* Caches references to the EditText and ImageView objects in
* data members to optimize subsequent access.
*/
mUrlEditText = (EditText) findViewById(R.id.mUrlEditText);
mImageView = (ImageView) findViewById(R.id.mImageView);
}
/**
* Show a toast, notifying a user of an error when retrieving a
* bitmap.
*/
void showErrorToast(String errorString) {
Toast.makeText(this,
errorString,
Toast.LENGTH_LONG).show();
}
/**
* Display a downloaded bitmap image if it's non-null; otherwise,
* it reports an error via a Toast.
*
* @param image
* The bitmap image
*/
void displayImage(Bitmap image)
{
if (mImageView == null)
showErrorToast("Problem with Application,"
+ " please contact the Developer.");
else if (image != null)
mImageView.setImageBitmap(image);
else
showErrorToast("image is corrupted,"
+ " please check the requested URL.");
}
/**
* Called when a user clicks a button to reset an image to
* default.
*
* @param view
* The "Reset Image" button
*/
public void resetImage(View view) {
mImageView.setImageResource(R.drawable.default_image);
}
/**
* Called when a user clicks the Download Image button to download
* an image using the DownloadService
*
* @param view
* The "Download Image" button
*/
public void downloadImage(View view) {
// Obtain the requested URL from the user input.
if (mIsBound) {
String url = getUrlString();
Log.e(DownloadActivity.class.getSimpleName(),
"Downloading " + url);
hideKeyboard();
// Inform the user that the download is starting.
showDialog("downloading via startService()");
// Create a request Message that indicates the Service should
// send the reply back to ReplyHandler encapsulated by the
// Messenger.
Message msg = Message.obtain(null, LOG_OP);
Bundle bundle = new Bundle();
bundle.putString(MESSAGE_URL, url);
msg.setData(bundle);
// Message request = Message.obtain();
msg.replyTo = new Messenger(new DownloadHandler(this));
try {
if (mMessengerRef != null) {
Log.d(TAG, "sending message to service with url");
// Send the request Message to the
// UniqueIDGeneratorService.
mMessengerRef.send(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
// Create an Intent to download an image in the background via
// a Service. The downloaded image is later diplayed in the
// UI Thread via the downloadHandler() method defined below.
// DownloadService.makeIntent(this, Uri.parse( getUrlString()));
}else{
Log.d(TAG, "service is not bounded restat again");
}
}
/**
* Hook method called by Android when this Activity becomes
* visible.
*/
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart()");
Log.d(TAG, "calling bindService()");
if (mMessengerRef == null)
// Bind to the UniqueIDGeneratorService associated with this
// Intent.
bindService(DownloadService.makeIntent(this),
this.mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mIsBound)
unbindService(mConnection);
}
/**
* @class DownloadHandler
*
* @brief An inner class that inherits from Handler and uses its
* handleMessage() hook method to process Messages sent to
* it from the DownloadService.
*/
private static class DownloadHandler extends Handler {
/**
* Allows Activity to be garbage collected properly.
*/
private WeakReference<DownloadActivity> mActivity;
/**
* Class constructor constructs mActivity as weak reference
* to the activity
*
* @param activity
* The corresponding activity
*/
public DownloadHandler(DownloadActivity activity) {
mActivity = new WeakReference<DownloadActivity>(activity);
}
/**
/**
* This hook method is dispatched in response to receiving
* the pathname back from the DownloadService.
*/
public void handleMessage(Message msg) {
DownloadActivity activity = mActivity.get();
// Bail out of the DownloadActivity is gone.
if (activity == null)
return;
// Extract the data from Message, which is in the form
// of a Bundle that can be passed across processes.
Bundle data = msg.getData();
// Extract the pathname from the Bundle.
String pathname = data.getString("PATHNAME");
// See if things worked or not.
if (msg.arg1 != RESULT_OK || pathname == null)
activity.showDialog("failed download");
// Stop displaying the progress dialog.
activity.dismissDialog();
// Display the image in the UI Thread.
activity.displayImage(BitmapFactory.decodeFile(pathname));
}
};
/**
* Display the Dialog to the User.
*
* @param message
* The String to display what download method was used.
*/
public void showDialog(String message) {
mProgressDialog =
ProgressDialog.show(this,
"Download",
message,
true);
}
/**
* Dismiss the Dialog
*/
public void dismissDialog() {
if (mProgressDialog != null)
mProgressDialog.dismiss();
}
/**
* Hide the keyboard after a user has finished typing the url.
*/
private void hideKeyboard() {
InputMethodManager mgr =
(InputMethodManager) getSystemService
(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(mUrlEditText.getWindowToken(),
0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.download, menu);
return true;
}
/**
* Read the URL EditText and return the String it contains.
*
* @return String value in mUrlEditText
*/
String getUrlString() {
String s = mUrlEditText.getText().toString();
if (s.equals(""))
s = mDefaultUrl;
return s;
}
}