为什么IntentReceiver泄露?

时间:2014-05-25 01:28:52

标签: java android bluetooth

我想从蓝牙服务器收到一个String这是我有一个java代码但是当我运行我的Android客户端Activity时它会向我显示这个异常

Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1@410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1@410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
        at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:792)
        at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
        at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1111)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1098)
        at android.app.ContextImpl.registerReceiver(ContextImpl.java:1092)
        at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:365)
        at com.waseem.mobileclient.bluetoot_app.MainActivity.onCreate(MainActivity.java:68)
        at android.app.Activity.performCreate(Activity.java:5008)

我在onPause()取消注册为什么我得到这个例外请帮助我它已经困扰了我很长一段时间。 这是客户端代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (myBluetoothAdapter == null) {
        Log.e(TAG, "No Bluetooth Adapter available. Exiting...");
        this.finish();
    }
    IntentFilter intent_filter=new IntentFilter(MESSAGE_RECEIVED_INTENT);
    broad_receiver=new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(MESSAGE_RECEIVED_INTENT)) {
                showInformation(intent.getExtras().getString("Message"), 5000);
                getVibrator().vibrate(500);
            }
            else {
                showInformation("Message unable to receive", 5000);
                getVibrator().vibrate(500);
            }
        }
    };

    this.registerReceiver(broad_receiver,intent_filter);
    Button start_server = (Button)findViewById(R.id.button_start);
    start_server.setOnClickListener(this);

    Button stop_server = (Button)findViewById(R.id.button_stop);
    stop_server.setOnClickListener(this);

}

@Override
protected void onPause() {
    this.unregisterReceiver(this.broad_receiver);
    super.onPause();

    server.cancel();
    restoreBTDeviceName();

}

@Override
public void onClick(View v) {
    Button btn = (Button) v;
    if (btn.getId() == R.id.button_start) {
        if (!myBluetoothAdapter.getName().startsWith(PREFIX))
            myBluetoothAdapter.setName(PREFIX );

        if (myBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            requestBTDiscoverable();
            server = new AcceptThread();
            server.start();

            btn.setEnabled(false);

            ((Button) this.findViewById(R.id.button_stop)).setEnabled(true);
        }
    } else if (btn.getId() == R.id.button_stop) {
        server.cancel();
        btn.setEnabled(false);
        ((Button) this.findViewById(R.id.button_start)).setEnabled(true);

        restoreBTDeviceName();
    }

}

/**
 * Launches Discoverable Bluetooth Intent.
 */
public void requestBTDiscoverable() {
    Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
    i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);

    startActivityForResult(i, REQUEST);

    int result = 0;

    this.onActivityResult(REQUEST, result, i);
    Log.i(TAG, "Bluetooth discoverability enabled");
}

/**
 * Obtains the Vibrator service.
 *
 * @return Vibrator Object.
 */
private Vibrator getVibrator() {

    return (Vibrator) getSystemService(VIBRATOR_SERVICE);
}

/**
 * Removes the prefix from the device name if the prefix is present.
 */
private void restoreBTDeviceName() {
    if (myBluetoothAdapter.getName().startsWith(PREFIX))
        myBluetoothAdapter.setName(myBluetoothAdapter.getName().substring(PREFIX.length()));
}

/**
 * Shows a information dialog.
 *
 * @param message  String resource used to define the message.
 * @param duration Dialog's TTL.
 */
private void showInformation(String message, long duration) {
    final Dialog mDialog = new Dialog(this);

    TextView txt = new TextView(this);
    txt.setText(message);
    mDialog.setContentView(txt);
    mDialog.setTitle("Information");
    mDialog.show();

    (new Handler()).postDelayed(new Runnable() {
        public void run() {
            mDialog.dismiss();
        }
    },duration); // Close dialog after delay
}


/**
 * ************************************* AcceptThread *************************************
 */
class AcceptThread extends Thread {
    /**
     * Tag that will appear in the log.
     */
    private final String ACCEPT_TAG = AcceptThread.class.getName();

    /**
     * The bluetooth server socket.
     */
    private final BluetoothServerSocket mServerSocket;

    public AcceptThread() {
        BluetoothServerSocket tmp = null;
        try {
            tmp = myBluetoothAdapter.listenUsingRfcommWithServiceRecord(ACCEPT_TAG, UUID.fromString(defaultUUID));
        } catch (IOException e) {
            e.printStackTrace();
        }
        mServerSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;
        while (true) {
            try {
                Log.i(ACCEPT_TAG, "Listening for a connection...");

                socket = mServerSocket.accept();
                Log.i(ACCEPT_TAG, "Connected to " + socket.getRemoteDevice().getName());

            } catch (IOException e) {
                break;
            }
            // If a connection was accepted
            if (socket != null) {
                // Do work to manage the connection (in a separate thread)
                try {
                    // Read the incoming string.
                    String buffer;

                    DataInputStream in = new DataInputStream(socket.getInputStream());

                    buffer = in.readUTF();

                    Intent i = new Intent(MESSAGE_RECEIVED_INTENT);
                    i.putExtra("Message", String.format("%sn From: %s", buffer, socket.getRemoteDevice().getName()));

                    getBaseContext().sendBroadcast(i);
                } catch (IOException e) {
                    Log.e(ACCEPT_TAG, "Error obtaining InputStream from socket");
                    e.printStackTrace();
                }
                try {
                    mServerSocket.close();
                } catch (IOException e) {
                }
                break;
            }
        }

    }

    /**
     * Will cancel the listening socket, and cause the thread to finish
     */
    public void cancel() {
        try {
            mServerSocket.close();
        } catch (IOException e) {
        }
    }
}

1 个答案:

答案 0 :(得分:6)

LogCat的第一行说:

  

您是否错过了对unregisterReceiver()的调用?

这只是意味着您需要查看BroadcastReceiver的API文档以寻求帮助,其中包含:

  

注意: 如果在Activity.onResume()实施中注册接收者,则应在Activity.onPause()中取消注册。 (暂停时不会收到意图,这将减少不必要的系统开销)。不要在Activity.onSaveInstanceState()中取消注册,因为如果用户在历史堆栈中向后移动,则不会调用此方法。