PhoneStateListener memery leaked ( LeakCanary ) 手机来电状态监听,泄漏无法解决
来源:互联网 发布:pro recorder软件下载 编辑:程序博客网 时间:2024/06/03 17:02
1、问题
用LeakCanary 分析手机app的泄漏情况, 发现有监听手机状态的界面全部泄漏,试了很久,都没有改成功
2、手机来电状态监听
2.1、权限
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
2.2、普通代码(会泄漏)
//注册 public void register(PhoneStateListener listener) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE); tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); }//销毁 public void unRegister(PhoneStateListener listener) { if (tm != null) { tm.listen(listener, PhoneStateListener.LISTEN_NONE); tm = null; } }
3、改为弱引用, 子线程注册 (依旧泄漏)
TelephonyManager tm; WeakReference<Context> weakReference;//注册 public void register(PhoneStateListener listener) { new Thread(new Runnable() { @Override public void run() { tm = (TelephonyManager) weakReference.get().getSystemService(Service.TELEPHONY_SERVICE); tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); } }).start(); }//销毁 public void unRegister(PhoneStateListener listener) { if (tm != null) { tm.listen(listener, PhoneStateListener.LISTEN_NONE); tm = null; } }
4、结论
查的几种方式 是都会泄漏, 不管listener ,tm 最终设置为null 还是弱引用,子线程操作什么的。
5、改进(无法释放, 规避 tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE) 概率)
在做手机来电状态监听时, 直接操作TelephonyManager 的方法是方便了很多,但是会使得context一直持有,泄漏。 改进方式是把使用方式写全,先监听电话广播,识别到是来电,再用TelephonyManager设置PhoneStateListener,这样子就只有来电时那个 Activity 是泄漏的, 并且使用弱引用。(没使用子线程注册)。
public class LogicTelephonyManager { final private String TAG = "LogicTelephonyManager"; TelephonyManager tm; WeakReference<Context> weakReference; IntentFilter intentFilterPhone; PhoneReceiver receiver; public LogicTelephonyManager(Context context) { // this.context = context; weakReference = new WeakReference<Context>(context); intentFilterPhone = new IntentFilter(); intentFilterPhone.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); receiver = new PhoneReceiver(); context.registerReceiver(receiver, intentFilterPhone); }//注册 public void register(PhoneStateListener listener) {// new Thread(new Runnable() {// @Override// public void run() { tm = (TelephonyManager) weakReference.get().getSystemService(Service.TELEPHONY_SERVICE); tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);// }// }).start(); }//销毁 public void unRegister(PhoneStateListener listener) { if (context != null) { context.unregisterReceiver(receiver); } if (tm != null) { tm.listen(listener, PhoneStateListener.LISTEN_NONE); tm = null; } } public class PhoneReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { // 如果是去电(拨出) } else { //不是去电当成来电 //TODO:可以在这里做注册。 不过我的业务是把他发射出去在接收端进行注册绑定 listener EventBus.getDefault().post(new PhoneReceiverEvent()); } } }}
场景类
public class XXP {
LogicTelephonyManager telephonyManagerUtil; public XXP(Activity activity) {
EventBus.getDefault().register(this);
telephonyManagerUtil = new LogicTelephonyManager(activity);
}
@Subscribe
public void onEvent(PhoneReceiverEvent event) {
if (event != null) {
LogDebugUtil.i("LogicTelephonyManager", "PhoneReceiverEvent = " + event);
if (telephonyManagerUtil != null) {
telephonyManagerUtil.register(listener);
}
}
} public void onDestroy() {
EventBus.getDefault().unregister(this);
if (telephonyManagerUtil != null) {
telephonyManagerUtil.unRegister(listener);
}
System.gc();
}
PhoneStateListener listener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { //注意,方法必须写在super方法后面,否则incomingNumber无法获取到值。 super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: LogDebugUtil.d(TAG, "挂断"); break; case TelephonyManager.CALL_STATE_OFFHOOK: LogDebugUtil.d(TAG, "接听"); break; case TelephonyManager.CALL_STATE_RINGING: LogDebugUtil.d(TAG, "响铃:来电号码" + incomingNumber); //输出来电号码 break; } } }; }
6、补充
这个或许就是为什么要注册广播, 再注册监听方法吧。 因为监听后无法释放 也是尴尬。 有能路过能解决的 倒是可以留言指导下
0 0
- PhoneStateListener memery leaked ( LeakCanary ) 手机来电状态监听,泄漏无法解决
- 监听手机来电PhoneStateListener
- 监听手机状态--PhoneStateListener
- 监听手机状态--PhoneStateListener
- 监听手机状态之PhoneStateListener
- 举例说明在android中用PhoneStateListener监听手机电话状态与用发送邮件来通知来电电话的号码
- iOS 监听手机来电状态
- 监听手机拨打电话的状态 private PhoneStateListener getPhoneStateListener()
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- Android中监听手机来电及状态
- Android获取手机状态和监听手机来电状态
- Android获取手机状态和监听手机来电状态
- 引入LeakCanary监听内存泄漏
- symbian 监听来电状态
- symbian 监听来电状态
- 监听来电状态
- eclipse maven 创建web项目
- python读取txt文件中的数据
- 关于JNDI那点事
- 《Training:Running Your App》
- zoj1002
- PhoneStateListener memery leaked ( LeakCanary ) 手机来电状态监听,泄漏无法解决
- Volley的简单的二次回调封装
- Guava ByteSreams 常用方法的封装,FileInputStream的兄弟ByteArrayInputSteam,装饰类大兄弟DataOutputStream
- hdu2031
- Git2-常用命令
- nlp homework 03
- C 语言资源大全中文版
- hdu 4821 String 字符串hash
- 华为OJ——删除字符串中出现次数最少的