您的位置:首页 > Web前端 > CSS

实现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.     总结

从实现这个需求过程中,我们发现当我们对原生代码修改时,需要多加注意,因为我们可能会因为实现需求而改出更严重的问题,因为我们要在修改后,进行多方面的测试,已保证需求的完善!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android layout 应用