Android 使用新线程时出现异常
Android exception when use new Thread
大家好,我正在尝试制作一个应用程序,通过 Toast 消息实时获取我的电池状态。所以,如果我插入电池充电器,它应该显示 "battery is charging",如果我拔下充电器,它应该显示 "battery is discharging",等等...为此我使用了一个新线程,但在运行时我的应用程序崩溃我在 logcat
中收到错误
这是我的代码和logcat:
public class MainActivity extends Activity {
Context cxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn = (Button) findViewById(R.id.button);
cxt = this;
Runnable myRunnable = new Runnable() {
@Override
public void run() {
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent BatteryStatus = cxt.registerReceiver(null, IF);
int status = BatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
Toast.makeText(getBaseContext(), "La batteria è in carica", Toast.LENGTH_SHORT).show();
}
if (disCharging) {
Toast.makeText(getBaseContext(), "La batteria è in scarica", Toast.LENGTH_SHORT).show();
}
if (usbCharge) {
Toast.makeText(getBaseContext(), "La batteria è in carica tramite USB", Toast.LENGTH_SHORT).show();
}
if (acCharging) {
Toast.makeText(getBaseContext(), "La batteria è in carica tramite AC", Toast.LENGTH_SHORT).show();
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
这是我在 logcat 中遇到的错误:
01-04 11:10:10.696 7706-7723/com.example.matteo.battery E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-4343
Process: com.example.matteo.battery, PID: 7706
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.widget.Toast$TN.<init>(Toast.java:336)
at android.widget.Toast.<init>(Toast.java:100)
at android.widget.Toast.makeText(Toast.java:250)
at com.example.matteo.battery.MainActivity.run(MainActivity.java:43)
at java.lang.Thread.run(Thread.java:818)
我想我在尝试启动新线程时出错了。
谢谢大家!
您无法在非 UI 主题中更新您的 UI,
您在 Toast
消息中收到错误,
如果你想在新线程中做一些代码并在更新 UI 之后你可以使用 AsyncTask
,有关在新线程中更新 ui 的更多信息你可以看到 Update UI from Thread or see Documentation
您尝试实现的结果可以使用广播接收器更轻松地完成。
查看 android 开发者网站的以下 official Documentation。
试试这个
if (isCharging) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "La batteria è in carica", Toast.LENGTH_SHORT).show();
}
});
}
应用于所有 Toast
不使用线程。创建一个 BroadcastReceiver
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
//your code
}
};
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, IF);
或
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Thread myThread = new Thread(myRunnable);
myThread.start();
}
};
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, IF);
使用 runOnUiThread 在 UI 线程上 运行 指定的操作。
public class MainActivity extends Activity {
Context cxt;
Button bn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn = (Button) findViewById(R.id.button);
cxt = this;
Runnable myRunnable = new Runnable() {
@Override
public void run() {
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent BatteryStatus = cxt.registerReceiver(null, IF);
int status = BatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
showMessage("La batteria è in carica");
}
if (disCharging) {
showMessage("La batteria è in scarica");
}
if (usbCharge) {
showMessage("La batteria è in carica tramite USB");
}
if (acCharging) {
showMessage("La batteria è in carica tramite AC");
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
private void showMessage(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
}
大家好,我正在尝试制作一个应用程序,通过 Toast 消息实时获取我的电池状态。所以,如果我插入电池充电器,它应该显示 "battery is charging",如果我拔下充电器,它应该显示 "battery is discharging",等等...为此我使用了一个新线程,但在运行时我的应用程序崩溃我在 logcat
中收到错误这是我的代码和logcat:
public class MainActivity extends Activity {
Context cxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn = (Button) findViewById(R.id.button);
cxt = this;
Runnable myRunnable = new Runnable() {
@Override
public void run() {
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent BatteryStatus = cxt.registerReceiver(null, IF);
int status = BatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
Toast.makeText(getBaseContext(), "La batteria è in carica", Toast.LENGTH_SHORT).show();
}
if (disCharging) {
Toast.makeText(getBaseContext(), "La batteria è in scarica", Toast.LENGTH_SHORT).show();
}
if (usbCharge) {
Toast.makeText(getBaseContext(), "La batteria è in carica tramite USB", Toast.LENGTH_SHORT).show();
}
if (acCharging) {
Toast.makeText(getBaseContext(), "La batteria è in carica tramite AC", Toast.LENGTH_SHORT).show();
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
这是我在 logcat 中遇到的错误:
01-04 11:10:10.696 7706-7723/com.example.matteo.battery E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-4343
Process: com.example.matteo.battery, PID: 7706
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.widget.Toast$TN.<init>(Toast.java:336)
at android.widget.Toast.<init>(Toast.java:100)
at android.widget.Toast.makeText(Toast.java:250)
at com.example.matteo.battery.MainActivity.run(MainActivity.java:43)
at java.lang.Thread.run(Thread.java:818)
我想我在尝试启动新线程时出错了。
谢谢大家!
您无法在非 UI 主题中更新您的 UI,
您在 Toast
消息中收到错误,
如果你想在新线程中做一些代码并在更新 UI 之后你可以使用 AsyncTask
,有关在新线程中更新 ui 的更多信息你可以看到 Update UI from Thread or see Documentation
您尝试实现的结果可以使用广播接收器更轻松地完成。 查看 android 开发者网站的以下 official Documentation。
试试这个
if (isCharging) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "La batteria è in carica", Toast.LENGTH_SHORT).show();
}
});
}
应用于所有 Toast
不使用线程。创建一个 BroadcastReceiver
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
//your code
}
};
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, IF);
或
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Thread myThread = new Thread(myRunnable);
myThread.start();
}
};
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, IF);
使用 runOnUiThread 在 UI 线程上 运行 指定的操作。
public class MainActivity extends Activity {
Context cxt;
Button bn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn = (Button) findViewById(R.id.button);
cxt = this;
Runnable myRunnable = new Runnable() {
@Override
public void run() {
IntentFilter IF = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent BatteryStatus = cxt.registerReceiver(null, IF);
int status = BatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean disCharging = status == BatteryManager.BATTERY_STATUS_DISCHARGING;
boolean usbCharge = status == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = status == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
showMessage("La batteria è in carica");
}
if (disCharging) {
showMessage("La batteria è in scarica");
}
if (usbCharge) {
showMessage("La batteria è in carica tramite USB");
}
if (acCharging) {
showMessage("La batteria è in carica tramite AC");
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
private void showMessage(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
}