Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.bluetooth;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.app.DialogFragment;
     22 import android.bluetooth.BluetoothAdapter;
     23 import android.content.BroadcastReceiver;
     24 import android.content.Context;
     25 import android.content.DialogInterface;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.os.Bundle;
     29 import android.text.Editable;
     30 import android.text.InputFilter;
     31 import android.text.TextWatcher;
     32 import android.util.Log;
     33 import android.view.LayoutInflater;
     34 import android.view.View;
     35 import android.widget.Button;
     36 import android.widget.EditText;
     37 
     38 import com.android.settings.R;
     39 
     40 /**
     41  * Dialog fragment for renaming the local Bluetooth device.
     42  */
     43 public final class BluetoothNameDialogFragment extends DialogFragment implements TextWatcher {
     44     private static final int BLUETOOTH_NAME_MAX_LENGTH_BYTES = 248;
     45 
     46     private AlertDialog mAlertDialog;
     47     private Button mOkButton;
     48 
     49     // accessed from inner class (not private to avoid thunks)
     50     static final String TAG = "BluetoothNameDialogFragment";
     51     final LocalBluetoothAdapter mLocalAdapter;
     52     EditText mDeviceNameView;
     53 
     54     // This flag is set when the name is updated by code, to distinguish from user changes
     55     private boolean mDeviceNameUpdated;
     56 
     57     // This flag is set when the user edits the name (preserved on rotation)
     58     private boolean mDeviceNameEdited;
     59 
     60     // Key to save the edited name and edit status for restoring after rotation
     61     private static final String KEY_NAME = "device_name";
     62     private static final String KEY_NAME_EDITED = "device_name_edited";
     63 
     64     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
     65         @Override
     66         public void onReceive(Context context, Intent intent) {
     67             String action = intent.getAction();
     68             if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
     69                 updateDeviceName();
     70             } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) &&
     71                     (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) ==
     72                             BluetoothAdapter.STATE_ON)) {
     73                 updateDeviceName();
     74             }
     75         }
     76     };
     77 
     78     public BluetoothNameDialogFragment() {
     79         LocalBluetoothManager localManager = LocalBluetoothManager.getInstance(getActivity());
     80         mLocalAdapter = localManager.getBluetoothAdapter();
     81     }
     82 
     83     @Override
     84     public Dialog onCreateDialog(Bundle savedInstanceState) {
     85         String deviceName = mLocalAdapter.getName();
     86         if (savedInstanceState != null) {
     87             deviceName = savedInstanceState.getString(KEY_NAME, deviceName);
     88             mDeviceNameEdited = savedInstanceState.getBoolean(KEY_NAME_EDITED, false);
     89         }
     90         mAlertDialog = new AlertDialog.Builder(getActivity())
     91                 .setIcon(android.R.drawable.ic_dialog_info)
     92                 .setTitle(R.string.bluetooth_rename_device)
     93                 .setView(createDialogView(deviceName))
     94                 .setPositiveButton(R.string.bluetooth_rename_button,
     95                         new DialogInterface.OnClickListener() {
     96                             public void onClick(DialogInterface dialog, int which) {
     97                                 if (mLocalAdapter != null) {
     98                                     String deviceName = mDeviceNameView.getText().toString();
     99                                     Log.d(TAG, "Setting device name to " + deviceName);
    100                                     mLocalAdapter.setName(deviceName);
    101                                 }
    102                             }
    103                         })
    104                 .setNegativeButton(android.R.string.cancel, null)
    105                 .create();
    106 
    107         return mAlertDialog;
    108     }
    109 
    110     @Override
    111     public void onSaveInstanceState(Bundle outState) {
    112         outState.putString(KEY_NAME, mDeviceNameView.getText().toString());
    113         outState.putBoolean(KEY_NAME_EDITED, mDeviceNameEdited);
    114     }
    115 
    116     private View createDialogView(String deviceName) {
    117         final LayoutInflater layoutInflater = (LayoutInflater)getActivity()
    118             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    119         View view = layoutInflater.inflate(R.layout.dialog_edittext, null);
    120         mDeviceNameView = (EditText) view.findViewById(R.id.edittext);
    121         mDeviceNameView.setFilters(new InputFilter[] {
    122                 new Utf8ByteLengthFilter(BLUETOOTH_NAME_MAX_LENGTH_BYTES)
    123         });
    124         mDeviceNameView.setText(deviceName);    // set initial value before adding listener
    125         mDeviceNameView.addTextChangedListener(this);
    126         return view;
    127     }
    128 
    129     @Override
    130     public void onDestroy() {
    131         super.onDestroy();
    132         mAlertDialog = null;
    133         mDeviceNameView = null;
    134         mOkButton = null;
    135     }
    136 
    137     @Override
    138     public void onResume() {
    139         super.onResume();
    140         if (mOkButton == null) {
    141             mOkButton = mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
    142             mOkButton.setEnabled(mDeviceNameEdited);    // Ok button enabled after user edits
    143         }
    144         IntentFilter filter = new IntentFilter();
    145         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    146         filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
    147         getActivity().registerReceiver(mReceiver, filter);
    148     }
    149 
    150     @Override
    151     public void onPause() {
    152         super.onPause();
    153         getActivity().unregisterReceiver(mReceiver);
    154     }
    155 
    156     void updateDeviceName() {
    157         if (mLocalAdapter != null && mLocalAdapter.isEnabled()) {
    158             mDeviceNameUpdated = true;
    159             mDeviceNameEdited = false;
    160             mDeviceNameView.setText(mLocalAdapter.getName());
    161         }
    162     }
    163 
    164     public void afterTextChanged(Editable s) {
    165         if (mDeviceNameUpdated) {
    166             // Device name changed by code; disable Ok button until edited by user
    167             mDeviceNameUpdated = false;
    168             mOkButton.setEnabled(false);
    169         } else {
    170             mDeviceNameEdited = true;
    171             if (mOkButton != null) {
    172                 mOkButton.setEnabled(s.length() != 0);
    173             }
    174         }
    175     }
    176 
    177     /* Not used */
    178     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    179     }
    180 
    181     /* Not used */
    182     public void onTextChanged(CharSequence s, int start, int before, int count) {
    183     }
    184 }
    185