活动 st.stxma.Activities.SelectDeviceActivity 已泄露 IntentReceiver

Posted

技术标签:

【中文标题】活动 st.stxma.Activities.SelectDeviceActivity 已泄露 IntentReceiver【英文标题】:Activity st.stxma.Activities.SelectDeviceActivity has leaked IntentReceiver 【发布时间】:2015-08-21 16:11:25 【问题描述】:

如何以及在哪里取消注册接收器?我搜索并发现您在 onPauseonCreate 方法中执行此操作,但在我的情况下,我将如何执行此操作?

08-21 10:32:02.291  12817-12817/st.stxma E/ActivityThread﹕
    Activity st.stxma.Activities.SelectDeviceActivity has leaked IntentReceiver
    st.stxma.STXmaBluetooth$1@41d763e8 that was originally registered here.
    Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked:
    Activity st.stxma.Activities.SelectDeviceActivity has leaked IntentReceiver
    st.stxma.STXmaBluetooth$1@41d763e8 that was originally registered here.
    Are you missing a call to unregisterReceiver()?
        at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:809)
        at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:610)
        at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1803)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1783)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1777)
        at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:479)
        at st.stxma.STXmaBluetooth.enableBluetooth(STXmaBluetooth.java:72)
        at st.stxma.Activities.SelectDeviceActivity.scanForDevices(SelectDeviceActivity.java:90)
        at st.stxma.Activities.SelectDeviceActivity.scanForDevices(SelectDeviceActivity.java:101)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at android.view.View$1.onClick(View.java:3964)
        at android.view.View.performClick(View.java:4640)
        at android.view.View$PerformClick.run(View.java:19431)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5598)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
        at dalvik.system.NativeStart.main(Native Method)

SelectDeviceActivity.java

package st.stxma.Activities;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import java.util.Observable;
import java.util.Observer;
import st.stxma.R;
import st.stxma.STXmaApplication;



public class SelectDeviceActivity extends Activity implements Observer


    private STXmaApplication stx_app;
    private LinearLayout device_list;
    private Button disconnect_button;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    
        Log.w("STXma", "onCreate: Create!");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.select_device_relative_layout);
        stx_app = (STXmaApplication)getApplicationContext();
        stx_app.getModel().addObserver(this);

        device_list = (LinearLayout)findViewById(R.id.device_list);
        disconnect_button = (Button)findViewById(R.id.disconnect_button);

        populateDevices();         
    

    public void onPause()
    
        Log.w("STXma", "onPause: Halt Discovery!");
        super.onPause();
        stx_app.getControl().stxBluetooth().haltDiscovery();
    

    @Override
    public void onResume()
    
        Log.w("STXma", "onResume: Resume!");
        super.onResume();

        setDisconnectButton();
    

    void dummyDevice(View v)
    
        //Intent launch_device = new Intent(v.getContext(), DynamicControlActivity.class);
        Intent launch_device = new Intent(v.getContext(), DynamicControlViewPager.class);
        startActivity(launch_device);
    

    /*public void launchDevice(View v)
    
        //Intent launch_device = new Intent(v.getContext(), DynamicControlActivity.class);
        Intent launch_device = new Intent(v.getContext(), DynamicControlViewPager.class);
        startActivity(launch_device);
    */

    void scanForDevices()
    
        //  0.  Clear existing buttons
        stx_app.getModel().clearDeviceList();
        device_list.removeAllViews();

        //  1.  Turn on Bluetooth
        stx_app.getControl().stxBluetooth().enableBluetooth(this);



        //  2.  Scan for devices
        stx_app.getControl().stxBluetooth().startDiscovery();
    

    public void scanForDevices(View v)
    
        scanForDevices();
    

    void setDisconnectButton()
    

        BluetoothDevice dev = stx_app.getModel().getConnectedDevice();

        if(dev == null) 

            disconnect_button.setText("Not Connected");

        else

            disconnect_button.setText("Disconnect "+dev.getName());
        
    

    void populateDevices()
    
        device_list.removeAllViews();
        BluetoothDevice devices[] = stx_app.getModel().getDevices();

        if(devices == null)
        
            device_list.addView(createDummyButton());
            return;
        

        for(BluetoothDevice dev : devices)
        
            device_list.addView(createDeviceButton(dev));
        
    

    public void update(Observable obs, Object arg)
    
        BluetoothDevice dev = stx_app.getModel().getLastDeviceAdded();
        device_list.addView(createDeviceButton(dev));
    

    private Button createDummyButton()
    
        Button b = new Button(this);
        Drawable button_icon = this.getResources().getDrawable(R.drawable.st360);
        if (button_icon != null) 
            button_icon.setBounds(0, 0, 30, 30);
        
        b.setCompoundDrawables(button_icon, null, null, null);

        b.setText("Dummy Device");

        b.setOnClickListener(new OnClickListener()
            public void onClick(View v)
            
                dummyDevice(v);
            
        );

        return b;
    

    private Button createDeviceButton(BluetoothDevice dev)
    
        Button b = new Button(this);
        Drawable button_icon = this.getResources().getDrawable(R.drawable.st360);
        if (button_icon != null) 
            button_icon.setBounds(0, 0, 30, 30);
        
        b.setCompoundDrawables(button_icon, null, null, null);


        if ((dev.getName() != null) && (dev.getName().length() > 0)) 
            b.setText(dev.getName());
        else
            b.setText("Dummy Device");
        

        b.setOnClickListener(new OnClickListener()
            public void onClick(View v)
            
                Button b = (Button)v;
                BluetoothDevice dev = stx_app.getModel().getDeviceByName(b.getText().toString());

                if(dev != null)
                
                    //  Attempt to connect to the device
                    if(stx_app.getControl().connectDevice(dev))
                    
                        Intent launch_device = new Intent(v.getContext(), DynamicControlViewPager.class);
                        startActivity(launch_device);
                    
                    else Toast.makeText(SelectDeviceActivity.this, "Connection Failed", Toast.LENGTH_SHORT).show();
                
            
        );

        return b;
    

    public void disconnectFromDevice(View v)
    
        stx_app.getControl().disconnect();
        setDisconnectButton();
    

STXmaBluetooth.java

package st.stxma;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.UUID;


public class STXmaBluetooth 

    final static int REQUEST_ENABLE_BT = 1;
    BluetoothAdapter bt_adapter;
    BroadcastReceiver receiver;
    BluetoothSocket bt_socket;
    STXmaModel stx_model;
    Boolean connected = false;
    CommunicationThread comm_thread;
    ArrayList<String> message_fragment;

    public STXmaBluetooth(STXmaModel model)
    
        bt_adapter = BluetoothAdapter.getDefaultAdapter();
        stx_model = model;
        message_fragment = new ArrayList<String>();

        createReceiver();
    


    public boolean enableBluetooth(Activity blue_activity)
    
        Intent enable_bluetooth;
        //  Check to see if the device supports Bluetooth

        if(bt_adapter == null)
        

            Toast.makeText(blue_activity.getApplicationContext(), "No bluetooth detected",Toast.LENGTH_LONG).show();
            blue_activity.finish();
            //  Device does not support bluetooth - do something!
        

        //  Check to see if the Bluetooth is enabled
        //  If not, ask the user if they want to enable it
        if(!bt_adapter.isEnabled())
        

            enable_bluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            blue_activity.startActivityForResult(enable_bluetooth, REQUEST_ENABLE_BT);

        

        //  Enable Receiver

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        blue_activity.registerReceiver(receiver, filter);


        return true;
    


    private void createReceiver()
    
        receiver = new BroadcastReceiver()
        
            public void onReceive(Context context, Intent intent)
            
                //Log.w("STXma", "OnReceive called");
                //aa.notifyDataSetChanged();
                String action = intent.getAction();
                if(BluetoothDevice.ACTION_FOUND.equals(action))
                
                    //  Get the Bluetooth device object from the Intent
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    stx_model.addDevice(device);



                
            
        ;
    

    public void haltDiscovery()
    

        bt_adapter.cancelDiscovery();

    

    public boolean disconnect()
    
        try
        
            comm_thread.disconnect();
            bt_socket.close();
        
        catch(Exception e)
        
            Log.w("STXma", "disconnect(): "+e.getMessage());
            return false;
        
        Log.w("STXma", "Disconnected Now");
        stx_model.setConnectedDevice(null);
        return true;
    

    ////////////////////////////////////////////////////////////////////////////
    //  ************************************************************************
    //
    //  boolean connect(BluetoothDevice dev)
    //
    //  July 10th, 2014
    //
    //  This function creates a connection to the bluetooth device provided to
    //  it.  It returns true if successful.
    //
    //  Note:  enableCommunicationsThread() must be called to to open the device
    //  for communications.
    //
    //  ************************************************************************
    ////////////////////////////////////////////////////////////////////////////
    public boolean connect(BluetoothDevice dev)
    
        bt_adapter.cancelDiscovery();
        UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

        try
        
            bt_socket = dev.createRfcommSocketToServiceRecord(uuid);
            bt_socket.connect();
            stx_model.setConnectedDevice(dev);
        
        catch(IOException e)
        
            Log.w("STXma", "IOException in connect "+e.getMessage());
            connected = false;
        
        catch(Exception e)
        
            Log.w("STXma", "Exception in connect "+e.getMessage());
            connected = false;
        

        if(connected)
        
            Log.w("STXma", "Connection completed");
        

        connected = enableCommunicationsThread();

        return connected;
    

    ////////////////////////////////////////////////////////////////////////////
    //  ************************************************************************
    //
    //  boolean enableCommunicationsThread()
    //
    //  July 10th, 2014
    //
    //  This function creates and starts the communication thread.  Once started
    //  commands can be sent to the device and the software will read the BT
    //  responses
    //
    //  ************************************************************************
    ////////////////////////////////////////////////////////////////////////////
    private boolean enableCommunicationsThread()
    
        comm_thread = new CommunicationThread(bt_socket, this);
        comm_thread.start();
        return comm_thread.isConnected();        
    

    ////////////////////////////////////////////////////////////////////////////
    //  ************************************************************************
    //
    //  void sendCommand(String cmd)
    //
    //  July 10th, 2014
    //
    //  Converts the string command into an integer and sends it to the
    //  communication thread to be writen to the device.
    //
    //  ************************************************************************
    ////////////////////////////////////////////////////////////////////////////
    public void sendCommand(String cmd)
    
        try
        
            int i = Integer.decode(cmd);
            comm_thread.write(i); 
        
        catch(Exception e)
        
            Log.w("STXma", "Send Command Failed: "+e.getMessage());
                
    

    ////////////////////////////////////////////////////////////////////////////
    //  ************************************************************************
    //
    //  public void startDiscovery()
    //
    //  July 7th, 2014
    //
    //  This function clears the existing list of devices then starts the
    //  discovery process.
    //
    //  ************************************************************************
    ////////////////////////////////////////////////////////////////////////////
    public void startDiscovery()
    
        Log.w("STXma", "Start Discovery");
        bt_adapter.startDiscovery();
    

    public void processBuffer(Integer[] buffer)
    
        //Log.w("STXma", "Process Buffer");

        for(int value : buffer)
        
            String byte_string = Integer.toHexString(value);
            Log.w("STXma", "0x"+byte_string);


            message_fragment.add(byte_string);
            if(completedMessage())
            
                String byte_array[] = new String[message_fragment.size()];
                byte_array = message_fragment.toArray(byte_array);

                stx_model.processBluetoothMessage(byte_array);

                //  Clear the messages
                message_fragment.clear();
            

        

       

    ////////////////////////////////////////////////////////////////////////////
    //  ************************************************************************
    //
    //  boolean completedMessage()
    //
    //  July 21, 2014
    //
    //  There are three valid return sizes
    //  4X - These are all five byte messages.  The first is the command, the
    //      other four bytes are the data
    //  8X - These are two byte messages returned separately.  The first byte
    //      tells the device what is being set, the second is the value it
    //      sets it to
    //  XX - These are command bytes that are a single byte long
    //
    //  ************************************************************************
    ////////////////////////////////////////////////////////////////////////////
    private boolean completedMessage()
    
        //  If the message_fragment is empty, we do not have a valid return
        if(message_fragment.isEmpty())return false;

        //  If the first byte starts with a "4", we know we have a 5 byte
        //  return, so we need to collect 5 bytes before returning true
        String first = message_fragment.get(0);
        if(first.startsWith("4")) 
            return message_fragment.size() == 5;
        
        else if(first.startsWith("8"))
        
            return message_fragment.size() == 2;
        

        //  Any other size is a valid single byte command return
        return true;
    

【问题讨论】:

【参考方案1】:

创建一个方法onDestroy()并放入unregisterReceiver(broadcast)

【讨论】:

感谢您的回复。我是否在蓝牙类中创建 onDestroy() 方法?我对把这个方法放在哪里感到困惑? 在要取消注册的类中创建接收器。最好在所有类中创建一个方法onDestroy() 并取消注册接收器 但是当接收器在 STXmaBluetooth.java 类中注册时,如何从 SelectDeviceActivity.java 类中注销接收器?如果您查看代码的顶部,您将看到它是如何在 STXmaBluetooth 类的 enabledBluetooth 方法中注册的。可以举个例子吗? 您能否尝试将代码缩短为仅接收广播的部分。你像这样注销它。 unregisterReceiver(**name of the broadcast receiver instance that is the name of the variable you created as an instance of your broadcast receiver**) IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); blue_activity.registerReceiver(receiver, filter);

以上是关于活动 st.stxma.Activities.SelectDeviceActivity 已泄露 IntentReceiver的主要内容,如果未能解决你的问题,请参考以下文章

UML学习——活动图

UML建模(六)--活动图

Android:如何从活动活动中关闭前台活动?

从通知中导航到父活动

短说社区论坛系统——活动模块功能介绍

无法识别启动活动,未找到默认活动启动活动时出错