更新:我不同意这是重复的 - 因为我正在寻找退出主应用程序的方法,但仍然会从服务中显示Toast。
在a very simple test app我有2个按钮:
单击任何按钮将运行带有相应操作字符串的服务(“打开”或“闪烁”) -
public class OpenActivity extends Activity {
private Intent mServiceIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_open);
mServiceIntent = new Intent(this, RegionService.class);
}
public void openCar(View v) {
mServiceIntent.setAction("open");
startService(mServiceIntent);
}
public class RegionService extends IntentService {
private static final String TAG = "RegionService";
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "Received an intent: " + intent);
String action = intent.getAction();
Log.d(TAG, "Received an action: " + action);
if(action.equals("open")) {
Toast.makeText(this,
getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
不幸的是我的应用程序崩溃了:
D/RegionService(24506): Received an intent: Intent { act=open cmp=de.afarber.mynotification/.RegionService }
D/RegionService(24506): Received an action: open
W/MessageQueue(24506): Handler (android.os.Handler) {422768a8} sending message to a Handler on a dead thread
W/MessageQueue(24506): java.lang.RuntimeException: Handler (android.os.Handler) {422768a8} sending message to a Handler on a dead thread
W/MessageQueue(24506): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
W/MessageQueue(24506): at android.os.Handler.enqueueMessage(Handler.java:626)
W/MessageQueue(24506): at android.os.Handler.sendMessageAtTime(Handler.java:595)
W/MessageQueue(24506): at android.os.Handler.sendMessageDelayed(Handler.java:566)
W/MessageQueue(24506): at android.os.Handler.post(Handler.java:326)
W/MessageQueue(24506): at android.widget.Toast$TN.hide(Toast.java:370)
W/MessageQueue(24506): at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:54)
W/MessageQueue(24506): at android.os.Binder.execTransact(Binder.java:412)
W/MessageQueue(24506): at dalvik.system.NativeStart.run(Native Method)
作为Android编程新手,我想知道如何以正确的方式显示来自服务的Toast?
我想我已经在Android Home上看过Toasts(即设备屏幕上没有活动,但仍然有Toasts)。
我的背景:我想从我的服务中监控一个信标设备并显示一些文本Toast - 即使我的应用已关闭。
答案 0 :(得分:34)
OnHandleIntent
将在差异Thread
中运行
所以你在android
Toast
所以改变你的代码
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
});
IntentService将创建一个线程来处理新意图,并在任务完成后立即终止它。所以,吐司将不受一个死线控制。
当屏幕上显示吐司时,您应该在控制台中看到一些例外。
答案 1 :(得分:5)
IntentService有一些限制:
它无法直接与您的用户界面互动。把它 在UI中,您必须将它们发送到活动。
一切都发生在后台线程而不是UI线程上,所以你需要一种不同的方式,如下所示:
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
}
@Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MyIntentService.this, "Hello Toast!", Toast.LENGTH_LONG).show();
}
});
}
答案 2 :(得分:2)
OnHandleIntent
,任何触摸UI的尝试都将导致崩溃。使用处理程序在UI线程上发布Runnable以显示您的吐司。
private class MyRunnable implements Runnable {
final int mTextId = -1;
final Context mContext;
public MyRunnable(Context c, int textId) {
mTextId = textId;
mContext = c;
}
@Override
public void run() {
Toast.makeText(mContext,
getString(mTextId),
Toast.LENGTH_SHORT).show();
}
}
Handler handler = new Handler();
handler.post(new MyRunnable(this, R.string.car_opened));
答案 3 :(得分:1)
使用以下代码:
runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
}
});
答案 4 :(得分:0)
这个问题是因为没有从main_thread运行Toast,为了克服这个问题,
在创建活动时,从onCreate()
方法保存它的上下文:
public static Context ctx;
// the method responsible for running the MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
}
然后,在服务中添加一个处理程序并从中运行一个线程(因为Handler是通过主线程执行的):
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(OpenActivity.ctx, getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
});