Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Activity has leaked IntentReceiver

I'm writing very simple app. It works OK, but when I hit a back key it crashes (Activity has leaked IntentReceiver that was originally registered here). This app should work in background. How to do it properly?

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class Bateria extends Activity implements OnClickListener, OnSeekBarChangeListener {

    ProgressBar pbBatteryLevel;
    TextView tvBatteryLevel;
    TextView tvLeft;
    RadioButton rbPercent;
    RadioButton rbTime;
    SeekBar sbSetLeft;
    boolean percent; // true - percent, false - time
    boolean informed;
    int progress;
    int MAX_TIME;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        PowerManager pM = (PowerManager) getSystemService(Context.POWER_SERVICE);
        WakeLock wL = pM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "whatever");
        long HOURS24 = 86400000;

        super.onCreate(savedInstanceState);

        wL.acquire(HOURS24);

        setContentView(R.layout.main);

        initialize();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        registerReceiver(batteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    }

    private void initialize() {
        // TODO Auto-generated method stub
        SharedPreferences preferences = getSharedPreferences("SP_BATTERY", 0);
        percent = preferences.getBoolean("percent", true);
        progress = preferences.getInt("progress", 0);
        informed = false;

        MAX_TIME = 72*60;

        pbBatteryLevel = (ProgressBar) findViewById(R.id.pbBatteryLevel);
        tvBatteryLevel = (TextView) findViewById(R.id.tvBatteryLevel);
        tvBatteryLevel.setTextSize(20);
        tvLeft = (TextView) findViewById(R.id.tvLeft);
        if(percent)
            tvLeft.setText(String.valueOf(progress) + " %");
        else{
            int minutes = MAX_TIME*progress/100;
            int hours = minutes / 60;
            minutes -= hours*60;
            tvLeft.setText(String.valueOf(hours) + "h " + String.valueOf(minutes) + "min");
        }
        rbPercent = (RadioButton) findViewById(R.id.rbPercent);
        rbPercent.setOnClickListener(this);
        rbPercent.setChecked(percent);
        rbTime = (RadioButton) findViewById(R.id.rbTime);
        rbTime.setOnClickListener(this);
        rbTime.setChecked(!percent);

        sbSetLeft = (SeekBar) findViewById(R.id.sbSetPercent);
        sbSetLeft.setOnSeekBarChangeListener(this);
        sbSetLeft.setProgress(progress);

        registerReceiver(batteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    }

    private BroadcastReceiver batteryInfoReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context c, Intent i) {
            int level = i.getIntExtra("level", 0);
            int voltage = i.getIntExtra("voltage", 0);
            int temperature = i.getIntExtra("temperature", 0);
            pbBatteryLevel.setProgress(level);
            tvBatteryLevel.setText("Battery Level: " + Integer.toString(level)
                    + "%" + "\n" + voltage + " mV " + temperature + " C");
            if(level < progress && !informed){
                //////////
                Toast.makeText(getApplicationContext(), "BATTERY", Toast.LENGTH_LONG).show();
                MediaPlayer mp = MediaPlayer.create(Bateria.this, R.raw.explosion);
                mp.start();
                //////////
                informed = true;
            }
            else if(level >= progress){
                informed = false;
            }
        }
    };

    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case(R.id.rbPercent):
            percent = true;
            tvLeft.setText(String.valueOf(progress) + " %");
            break;
        case(R.id.rbTime):
            percent = false;
            int minutes = MAX_TIME*progress/100;
            int hours = minutes / 60;
            minutes -= hours*60;
            tvLeft.setText(String.valueOf(hours) + "h " + String.valueOf(minutes) + "min");
            break;
        }

        SharedPreferences preferences = getSharedPreferences("SP_BATTERY", 0);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putBoolean("percent", percent);
        editor.commit();
    }

    public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
        // TODO Auto-generated method stub
        if(percent)
            tvLeft.setText(String.valueOf(progress) + " %");
        else{
            int minutes = MAX_TIME*progress/100;
            int hours = minutes / 60;
            minutes -= hours*60;
            tvLeft.setText(String.valueOf(hours) + "h " + String.valueOf(minutes) + "min");
        }

        this.progress = progress;
        SharedPreferences preferences = getSharedPreferences("SP_BATTERY", 0);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putInt("progress", progress);
        editor.commit();
        informed = false;
    }

    public void onStartTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub

    }

    public void onStopTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        super.onCreateOptionsMenu(menu);
        MenuInflater blowUp = getMenuInflater();
        blowUp.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // TODO Auto-generated method stub
        System.exit(0);
        return false;
    }
}
like image 428
user1411291 Avatar asked May 22 '12 22:05

user1411291


1 Answers

First of all you need to unregister a registered BroadcastReceiver as appropriate. See here for more information: http://developer.android.com/reference/android/content/BroadcastReceiver.html

More important than that, you cannot develop an application running in background by just developing an Activity. You need to develop a Service for that. Check this link for an explanation of how to do it, along with API documentation: http://developer.android.com/reference/android/app/Service.html

like image 140
Hakan Serce Avatar answered Sep 27 '22 17:09

Hakan Serce