实现FM在无耳机插入时退出后有弹出框提示及其样式
2014-11-17 14:13
148 查看
1. 背景
客户对FM在无耳机插入的状态下,有其特定需求。原生FM退出机制是在无耳机插入的状态下时,点击FM图标进入后,会有一个确定提示弹出框,提示用户需要插入耳机才可使用FM,当用户点击确定按钮后,FM将会退出!然后现在客户的需求是在无耳机插入的状态下,点击FM图标后,FM会立即退出,然后会弹出带图片和文字的Toast提示出来。下文将详细分析此需求的实现。
2. 原因分析 & 解决方法
首先我们用如下代码实现带图片和文字的Toast:
LayoutInflaterinflater=getLayoutInflater();
Viewlayout=inflater.inflate(R.layout.custome_toast_layout,(ViewGroup)findViewById(R.id.toast_layout_root));
ImageViewimageView=(ImageView)layout.findViewById(R.id.ivForToast);
imageView.setImageResource(R.drawable.fm_earphone);
TextViewtextView=(TextView)layout.findViewById(R.id.tvForToast);
textView.setText(R.string.dlg_noantenna_text);
Toast toast=newToast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0,40);
toast.setView(layout);
toast.show();
layout文件custome_toast_layout:
<?xmlversion="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_layout_root"
android:orientation="vertical"
android:background="@android:drawable/toast_frame"
android:layout_width="250dp"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/ivForToast"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
/>
<TextView
android:id="@+id/tvForToast"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:shadowColor="#BB000000"
android:shadowRadius="2.75"
/>
</LinearLayout>
这个Toast实现起来相对简单。
退出FM的代码如下:
exitService();
finish();
在原生代码中,无耳机插入的状态下会有一个确定提示弹出框,此部分代码的函数是:private void displayInsertEarphoneDialog() {……}
那我们把displayInsertEarphoneDialog()函数的原生代码屏蔽,而修改为:
exitService();
finish();
LayoutInflaterinflater=getLayoutInflater();
Viewlayout=inflater.inflate(R.layout.custome_toast_layout,(ViewGroup)findViewById(R.id.toast_layout_root));
ImageViewimageView=(ImageView)layout.findViewById(R.id.ivForToast);
imageView.setImageResource(R.drawable.fm_earphone);
TextViewtextView=(TextView)layout.findViewById(R.id.tvForToast);
textView.setText(R.string.dlg_noantenna_text);
Toasttoast=new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 40);
toast.setView(layout);
toast.show();
不就实现了客户的需求了吗!?
然后这样子会有一个严重的问题,就是无论是否有插入耳机,FM都退出,然后显示Toast提示框,FM无法正常使用!因此我们要继续分析源代码。
首先看看displayInsertEarphoneDialog()函数在那些地方被调用了。
有两处地方:
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); //注册耳机插入拔出的广播
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(ACTION_EXIT_FMRADIO);
//Register the filter receiver
registerReceiver(mHeadsetReceiver, filter);
booleanbOnAirplane = Settings.System.getInt(getContentResolver(),Settings.System.AIRPLANE_MODE_ON, 0) == 1;
if(bOnAirplane){
displayAirPlaneModeDialog();
}
if(!bIsHeadsetPlug){
displayInsertEarphoneDialog();
}else{
dismissInsertHeadsetDialog();
}
mIsActivityForeground = true;
if (null ==mService) {
LogUtils.d(TAG, "service has not bind finished");
return;
}
updateMenuStatus();
updateDialogStatus();
if(!isRecordFileExist()) {
mButtonPlayback.setEnabled(false);
}
}
另一处是在mHeadsetReceiver实现类里:
在onResume()函数里,由于bIsHeadsetPlug每次进入时都被赋值为FALSE,因此就会每次都会进入displayInsertEarphoneDialog()函数,所以就出现严重的问题。而在mHeadsetReceiver实现类里,当耳机拔出时就会执行displayInsertEarphoneDialog(),因此我们要解决上面说的严重问题,就把在onResume()函数里的displayInsertEarphoneDialog()屏蔽掉。
虽然这样貌似解决了,然后会出现另外一个严重问题,就是每次开机之后,在没有插入耳机的状态下,点击FM图标,每次都能进入FM,没有任何提示框,但只要有一次插入耳机后,FM就能恢复正常。显然这样子是不能满足客户的需求的。
后面经过代码及打印log信息分析得出,每次开机之后,在没有插入耳机之前,进入FM,系统是不会发出Intent.ACTION_HEADSET_PLUG广播的,因此就不会执行在mHeadsetReceiver类里的displayInsertEarphoneDialog()函数,而当有一次插入耳机之后,系统在每次进入FM后都会立即发出Intent.ACTION_HEADSET_PLUG广播。那如何解决这样一个问题呢?!
经过分析,我们需要设定一个变量:Settings.System.FMRADIO_EARPHONE_STATE,当每次开机完成后,都将这个值设为0,当插入耳机之后就将这个值设为1.当这个值为0的时候,在onResume()函数里执行displayInsertEarphoneDialog()函数,否则不执行。这样就可以解决这个问题了!
关于如何添加Settings.System.FMRADIO_EARPHONE_STATE变量,相信大家都知道,在此不做说明。那在哪里将Settings.System.FMRADIO_EARPHONE_STATE
值设为0,哪里设为1呢?
答案在SystemUI里,也就是状态栏应用!
在SystemUI/src/com/android/systemui/BootReceiver.java里添加:
Settings.System.putInt(context.getContentResolver(),Settings.System.FMRADIO_EARPHONE_STATE,0);
在SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java里:
于是,我们在onResume()函数里的修改如下:
3. 总结
从实现这个需求过程中,我们发现当我们对原生代码修改时,需要多加注意,因为我们可能会因为实现需求而改出更严重的问题,因为我们要在修改后,进行多方面的测试,已保证需求的完善!
客户对FM在无耳机插入的状态下,有其特定需求。原生FM退出机制是在无耳机插入的状态下时,点击FM图标进入后,会有一个确定提示弹出框,提示用户需要插入耳机才可使用FM,当用户点击确定按钮后,FM将会退出!然后现在客户的需求是在无耳机插入的状态下,点击FM图标后,FM会立即退出,然后会弹出带图片和文字的Toast提示出来。下文将详细分析此需求的实现。
2. 原因分析 & 解决方法
首先我们用如下代码实现带图片和文字的Toast:
LayoutInflaterinflater=getLayoutInflater();
Viewlayout=inflater.inflate(R.layout.custome_toast_layout,(ViewGroup)findViewById(R.id.toast_layout_root));
ImageViewimageView=(ImageView)layout.findViewById(R.id.ivForToast);
imageView.setImageResource(R.drawable.fm_earphone);
TextViewtextView=(TextView)layout.findViewById(R.id.tvForToast);
textView.setText(R.string.dlg_noantenna_text);
Toast toast=newToast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0,40);
toast.setView(layout);
toast.show();
layout文件custome_toast_layout:
<?xmlversion="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_layout_root"
android:orientation="vertical"
android:background="@android:drawable/toast_frame"
android:layout_width="250dp"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/ivForToast"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
/>
<TextView
android:id="@+id/tvForToast"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:shadowColor="#BB000000"
android:shadowRadius="2.75"
/>
</LinearLayout>
这个Toast实现起来相对简单。
退出FM的代码如下:
exitService();
finish();
在原生代码中,无耳机插入的状态下会有一个确定提示弹出框,此部分代码的函数是:private void displayInsertEarphoneDialog() {……}
那我们把displayInsertEarphoneDialog()函数的原生代码屏蔽,而修改为:
exitService();
finish();
LayoutInflaterinflater=getLayoutInflater();
Viewlayout=inflater.inflate(R.layout.custome_toast_layout,(ViewGroup)findViewById(R.id.toast_layout_root));
ImageViewimageView=(ImageView)layout.findViewById(R.id.ivForToast);
imageView.setImageResource(R.drawable.fm_earphone);
TextViewtextView=(TextView)layout.findViewById(R.id.tvForToast);
textView.setText(R.string.dlg_noantenna_text);
Toasttoast=new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 40);
toast.setView(layout);
toast.show();
不就实现了客户的需求了吗!?
然后这样子会有一个严重的问题,就是无论是否有插入耳机,FM都退出,然后显示Toast提示框,FM无法正常使用!因此我们要继续分析源代码。
首先看看displayInsertEarphoneDialog()函数在那些地方被调用了。
有两处地方:
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); //注册耳机插入拔出的广播
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(ACTION_EXIT_FMRADIO);
//Register the filter receiver
registerReceiver(mHeadsetReceiver, filter);
booleanbOnAirplane = Settings.System.getInt(getContentResolver(),Settings.System.AIRPLANE_MODE_ON, 0) == 1;
if(bOnAirplane){
displayAirPlaneModeDialog();
}
if(!bIsHeadsetPlug){
displayInsertEarphoneDialog();
}else{
dismissInsertHeadsetDialog();
}
mIsActivityForeground = true;
if (null ==mService) {
LogUtils.d(TAG, "service has not bind finished");
return;
}
updateMenuStatus();
updateDialogStatus();
if(!isRecordFileExist()) {
mButtonPlayback.setEnabled(false);
}
}
另一处是在mHeadsetReceiver实现类里:
在onResume()函数里,由于bIsHeadsetPlug每次进入时都被赋值为FALSE,因此就会每次都会进入displayInsertEarphoneDialog()函数,所以就出现严重的问题。而在mHeadsetReceiver实现类里,当耳机拔出时就会执行displayInsertEarphoneDialog(),因此我们要解决上面说的严重问题,就把在onResume()函数里的displayInsertEarphoneDialog()屏蔽掉。
虽然这样貌似解决了,然后会出现另外一个严重问题,就是每次开机之后,在没有插入耳机的状态下,点击FM图标,每次都能进入FM,没有任何提示框,但只要有一次插入耳机后,FM就能恢复正常。显然这样子是不能满足客户的需求的。
后面经过代码及打印log信息分析得出,每次开机之后,在没有插入耳机之前,进入FM,系统是不会发出Intent.ACTION_HEADSET_PLUG广播的,因此就不会执行在mHeadsetReceiver类里的displayInsertEarphoneDialog()函数,而当有一次插入耳机之后,系统在每次进入FM后都会立即发出Intent.ACTION_HEADSET_PLUG广播。那如何解决这样一个问题呢?!
经过分析,我们需要设定一个变量:Settings.System.FMRADIO_EARPHONE_STATE,当每次开机完成后,都将这个值设为0,当插入耳机之后就将这个值设为1.当这个值为0的时候,在onResume()函数里执行displayInsertEarphoneDialog()函数,否则不执行。这样就可以解决这个问题了!
关于如何添加Settings.System.FMRADIO_EARPHONE_STATE变量,相信大家都知道,在此不做说明。那在哪里将Settings.System.FMRADIO_EARPHONE_STATE
值设为0,哪里设为1呢?
答案在SystemUI里,也就是状态栏应用!
在SystemUI/src/com/android/systemui/BootReceiver.java里添加:
Settings.System.putInt(context.getContentResolver(),Settings.System.FMRADIO_EARPHONE_STATE,0);
在SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java里:
于是,我们在onResume()函数里的修改如下:
3. 总结
从实现这个需求过程中,我们发现当我们对原生代码修改时,需要多加注意,因为我们可能会因为实现需求而改出更严重的问题,因为我们要在修改后,进行多方面的测试,已保证需求的完善!
相关文章推荐
- Win10系统取消插入耳机后弹出的SmartAudio提示的方法
- Android实现退出界面弹出提示对话框
- 实现小功能:最后一个fragment,按返回键,弹出退出提示框
- mt6735 [Audio App]未插入耳机时进入收音机出现没有耳机提示框后,插入耳机FM能够自动播放
- asp.net 2.0 ajax中实现弹出窗口报警提示
- asp.net 2.0 ajax中实现弹出窗口报警提示
- Asp.net实现弹出窗口提示,又防止刷新被重复提交的方法
- 在Asp.net中如何实现弹出提示对话框
- Asp.net实现弹出窗口提示,又防止刷新被重复提交的方法
- 实现弹出"提示对话框"之后再进行"页面的转向"
- C#实现仿msn提示消息在登录后只弹出一次的效果(downmoon)
- 在Asp.net中如何实现弹出提示对话框
- 在Asp.net中如何实现弹出提示对话框
- C#+JS简单实现 定时轮询数据表 以及时弹出消息提示窗口
- c#里用VBSCRIPT 的MSGBOX实现弹出窗口提示(而不是警告)图标
- GridView中实现弹出提示框
- 实现弹出窗口提示
- 在Asp.net中如何实现弹出提示对话框
- C#实现类似MSN Messenger的弹出提示窗体
- C#+JS简单实现 定时轮询数据表 以及时弹出消息提示窗口