1 /* 2 * Copyright (C) 2014 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.fmradio.dialogs; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.Dialog; 22 import android.app.DialogFragment; 23 import android.content.DialogInterface; 24 import android.os.Bundle; 25 import android.text.Editable; 26 import android.text.TextWatcher; 27 import android.view.View; 28 import android.view.View.OnClickListener; 29 import android.view.WindowManager; 30 import android.widget.Button; 31 import android.widget.EditText; 32 import android.widget.Toast; 33 34 import com.android.fmradio.FmRecorder; 35 import com.android.fmradio.FmService; 36 import com.android.fmradio.R; 37 38 import java.io.File; 39 40 /** 41 * The dialog fragment for save recording file 42 */ 43 public class FmSaveDialog extends DialogFragment { 44 private static final String TAG = "FmSaveDialog"; 45 46 // save recording file button 47 private Button mButtonSave = null; 48 // discard recording file button 49 private Button mButtonDiscard = null; 50 // rename recording file edit text 51 private EditText mRecordingNameEditText = null; 52 // recording file default name 53 private String mDefaultRecordingName = null; 54 // recording file to save name 55 private String mRecordingNameToSave = null; 56 private OnRecordingDialogClickListener mListener = null; 57 58 // The default filename need't to check whether exist 59 private boolean mIsNeedCheckFilenameExist = false; 60 // record sd card path when start recording 61 private String mRecordingSdcard = null; 62 63 private String mRecordingFileName = null; 64 65 private String mTempRecordingName = null; 66 67 /** 68 * FM record dialog fragment, because fragment manager need empty 69 * constructor to instantiated this dialog fragment when configuration 70 * change 71 */ FmSaveDialog()72 public FmSaveDialog() { 73 } 74 75 /** 76 * FM record dialog fragment according name, should pass value recording 77 * file name 78 * 79 * @param defaultName The default file name in FileSystem 80 * @param recordingName The name in the dialog for show and save 81 */ FmSaveDialog(String sdcard, String defaultName, String recordingName)82 public FmSaveDialog(String sdcard, String defaultName, String recordingName) { 83 mRecordingSdcard = sdcard; 84 mTempRecordingName = defaultName + FmRecorder.RECORDING_FILE_EXTENSION; 85 mDefaultRecordingName = recordingName; 86 mRecordingNameToSave = recordingName; 87 } 88 89 @Override onAttach(Activity activity)90 public void onAttach(Activity activity) { 91 super.onAttach(activity); 92 try { 93 mListener = (OnRecordingDialogClickListener) activity; 94 } catch (ClassCastException e) { 95 e.printStackTrace(); 96 } 97 } 98 99 @Override onCreateDialog(Bundle savedInstanceState)100 public Dialog onCreateDialog(Bundle savedInstanceState) { 101 if (savedInstanceState != null) { 102 mRecordingNameToSave = savedInstanceState.getString("record_file_name"); 103 mDefaultRecordingName = savedInstanceState.getString("record_default_name"); 104 mRecordingSdcard = FmService.getRecordingSdcard(); 105 } 106 setStyle(STYLE_NO_TITLE, 0); 107 View view = getActivity().getLayoutInflater().inflate(R.layout.save_dialog, null); 108 mButtonSave = (Button) view.findViewById(R.id.save_dialog_button_save); 109 mButtonSave.setOnClickListener(mButtonOnClickListener); 110 111 mButtonDiscard = (Button) view.findViewById(R.id.save_dialog_button_discard); 112 mButtonDiscard.setOnClickListener(mButtonOnClickListener); 113 114 // Set the recording edit text 115 mRecordingNameEditText = (EditText) view.findViewById(R.id.save_dialog_edittext); 116 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setView(view); 117 return builder.create(); 118 } 119 120 @Override onDismiss(DialogInterface dialog)121 public void onDismiss(DialogInterface dialog) { 122 super.onDismiss(dialog); 123 if (mListener != null) { 124 mListener.onRecordingDialogClick(mRecordingFileName); 125 mListener = null; 126 } 127 } 128 129 /** 130 * Set the dialog edit text and other attribute 131 */ 132 @Override onResume()133 public void onResume() { 134 super.onResume(); 135 // have define in fm_recorder_dialog.xml length at most 136 // 250(maxFileLength - suffixLength) 137 if (mDefaultRecordingName != null) { 138 if (null != mRecordingNameToSave) { 139 // this case just for,fragment recreate 140 mRecordingNameEditText.setText(mRecordingNameToSave); 141 if ("".equals(mRecordingNameToSave)) { 142 mButtonSave.setEnabled(false); 143 } 144 } else { 145 mRecordingNameEditText.setText(mDefaultRecordingName); 146 } 147 } 148 149 mRecordingNameEditText.requestFocus(); 150 setTextChangedCallback(); 151 Dialog dialog = getDialog(); 152 dialog.setCanceledOnTouchOutside(false); 153 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE 154 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); 155 } 156 157 @Override onSaveInstanceState(Bundle outState)158 public void onSaveInstanceState(Bundle outState) { 159 outState.putString("record_file_name", mRecordingNameToSave); 160 outState.putString("record_default_name", mDefaultRecordingName); 161 super.onSaveInstanceState(outState); 162 } 163 164 /** 165 * This method register callback and set filter to Edit, in order to make 166 * sure that user input is legal. The input can't be illegal filename and 167 * can't be too long. 168 */ setTextChangedCallback()169 private void setTextChangedCallback() { 170 mRecordingNameEditText.addTextChangedListener(new TextWatcher() { 171 // not use, so don't need to implement it 172 @Override 173 public void afterTextChanged(Editable arg0) { 174 } 175 176 // not use, so don't need to implement it 177 @Override 178 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 179 } 180 181 /** 182 * check user input whether include invalid character 183 */ 184 @Override 185 public void onTextChanged(CharSequence s, int start, int before, int count) { 186 // Filename changed, so we should check the new filename is 187 // whether exist. 188 mIsNeedCheckFilenameExist = true; 189 String recordName = s.toString().trim(); 190 // Characters not allowed by file system 191 if (recordName.length() <= 0 192 || recordName.startsWith(".") 193 || recordName.matches(".*[/\\\\:*?\"<>|\t].*")) { 194 mButtonSave.setEnabled(false); 195 } else { 196 mButtonSave.setEnabled(true); 197 } 198 199 mRecordingNameToSave = mRecordingNameEditText.getText().toString().trim(); 200 } 201 }); 202 } 203 204 private OnClickListener mButtonOnClickListener = new OnClickListener() { 205 /** 206 * Define the button operation 207 */ 208 @Override 209 public void onClick(View v) { 210 211 File recordingFolderPath = new File(mRecordingSdcard, "FM Recording"); 212 213 switch (v.getId()) { 214 case R.id.save_dialog_button_save: 215 String msg = null; 216 // Check the recording name whether exist 217 mRecordingNameToSave = mRecordingNameEditText.getText().toString().trim(); 218 File recordingFileToSave = new File(recordingFolderPath, mRecordingNameToSave 219 + FmRecorder.RECORDING_FILE_EXTENSION); 220 221 if (mRecordingNameToSave.equals(mDefaultRecordingName)) { 222 mIsNeedCheckFilenameExist = false; 223 } else { 224 mIsNeedCheckFilenameExist = true; 225 } 226 227 if (recordingFileToSave.exists() && mIsNeedCheckFilenameExist) { 228 // show a toast notification if can't renaming a file/folder 229 // to the same name 230 msg = mRecordingNameEditText.getText().toString() + " " 231 + getActivity().getResources().getString(R.string.already_exists); 232 Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show(); 233 } else { 234 mRecordingFileName = mRecordingNameToSave; 235 dismissAllowingStateLoss(); 236 } 237 break; 238 239 case R.id.save_dialog_button_discard: 240 dismissAllowingStateLoss(); 241 // here need delete discarded recording file 242 File needToDelete = new File(recordingFolderPath, mTempRecordingName); 243 if (needToDelete.exists()) { 244 needToDelete.delete(); 245 } 246 break; 247 248 default: 249 break; 250 } 251 } 252 }; 253 254 /** 255 * The listener for click Save or Discard 256 */ 257 public interface OnRecordingDialogClickListener { 258 /** 259 * Record dialog click callback 260 * 261 * @param recordingName The user input recording name 262 */ onRecordingDialogClick(String recordingName)263 void onRecordingDialogClick(String recordingName); 264 } 265 } 266