xXJohnRamboXx
xXJohnRamboXx

Reputation: 739

Android exception when use new Thread

Hi guys i'm trying to make an app gets me battery status in real time through Toast message. So, if i plug battery charger it should me show "battery is charging", if i unplug charger it should me show "battery is discharging", etc...For this i'm using a new thread but on runtime my app crash and i get error in logcat

Here there are my code and 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();

}

This is the error i get in my 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$1.run(MainActivity.java:43)
        at java.lang.Thread.run(Thread.java:818)

I think i wrong something when try to start the new Thread.

Thanks everybody!

Upvotes: 0

Views: 126

Answers (4)

SorryForMyEnglish
SorryForMyEnglish

Reputation: 1181

try this

if (isCharging) {
    MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "La batteria è in carica", Toast.LENGTH_SHORT).show();
                }
            });
}

Apply to all Toast

not use thread. create a 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);

or

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);

Upvotes: 3

Hemanth
Hemanth

Reputation: 2737

Use runOnUiThread to run a specified action on the UI thread.

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();
            }
        });
    }
}

Upvotes: 1

Sanjeet A
Sanjeet A

Reputation: 5227

The Result you are trying to achieve can be done more easily using the Broadcast Receivers. Have a look on the following official Documentation of android developer site.

Upvotes: 1

Shayan Pourvatan
Shayan Pourvatan

Reputation: 11948

you can't update your UI in non UI thread,

you get an error in Toast message,

if you want do some code in new thread and after that updated UI you can use AsyncTask, for more info about updating ui in new thread you can see Update UI from Thread or see Documentation

Upvotes: 4

Related Questions