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.example.android.voicemail; 18 19 import com.example.android.voicemail.common.core.Voicemail; 20 import com.example.android.voicemail.common.core.VoicemailImpl; 21 import com.example.android.voicemail.common.core.VoicemailProviderHelper; 22 import com.example.android.voicemail.common.core.VoicemailProviderHelpers; 23 import com.example.android.voicemail.common.inject.InjectView; 24 import com.example.android.voicemail.common.inject.Injector; 25 import com.example.android.voicemail.common.logging.Logger; 26 import com.example.android.voicemail.common.ui.DialogHelperImpl; 27 import com.example.android.voicemail.common.utils.CloseUtils; 28 29 import android.app.Activity; 30 import android.app.Dialog; 31 import android.content.Intent; 32 import android.net.Uri; 33 import android.os.AsyncTask; 34 import android.os.Bundle; 35 import android.provider.MediaStore; 36 import android.util.Pair; 37 import android.view.View; 38 import android.widget.Button; 39 import android.widget.TextView; 40 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.io.OutputStream; 44 import java.text.ParseException; 45 import java.text.SimpleDateFormat; 46 import java.util.Date; 47 48 /** 49 * A simple activity that stores user entered voicemail data into voicemail content provider. To be 50 * used as a test voicemail source. 51 */ 52 public class AddVoicemailActivity extends Activity { 53 private static final Logger logger = Logger.getLogger(AddVoicemailActivity.class); 54 55 private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("dd/MM/yyyy h:mm"); 56 57 private static final int REQUEST_CODE_RECORDING = 100; 58 59 private final DialogHelperImpl mDialogHelper = new DialogHelperImpl(this); 60 /** 61 * This is created in {@link #onCreate(Bundle)}, and needs to be released in 62 * {@link #onDestroy()}. 63 */ 64 private VoicemailProviderHelper mVoicemailProviderHelper; 65 private Uri mRecordingUri; 66 67 // Mark the views as injectable. These objects are instantiated automatically during 68 // onCreate() by finding the appropriate view that matches the specified resource_id. 69 @InjectView(R.id.start_recording_btn) 70 private Button mStartRec; 71 @InjectView(R.id.save_btn) 72 private Button mSaveButton; 73 @InjectView(R.id.time) 74 private TextView mTime; 75 @InjectView(R.id.provider_package) 76 private TextView mProviderPackage; 77 @InjectView(R.id.mime_type) 78 private TextView mMimeType; 79 @InjectView(R.id.sender_number) 80 private TextView mSenderNumber; 81 @InjectView(R.id.duration) 82 private TextView mDuration; 83 84 /** Called when the activity is first created. */ 85 @Override 86 public void onCreate(Bundle savedInstanceState) { 87 super.onCreate(savedInstanceState); 88 setContentView(R.layout.add_voicemail); 89 // Inject all objects that are marked by @InjectView annotation. 90 Injector.get(this).inject(); 91 mVoicemailProviderHelper = VoicemailProviderHelpers.createPackageScopedVoicemailProvider(this); 92 93 setDefaultValues(); 94 95 // Record voice button. 96 mStartRec.setOnClickListener(new View.OnClickListener() { 97 @Override 98 public void onClick(View v) { 99 startRecording(); 100 } 101 }); 102 103 // Save voicemail button. 104 mSaveButton.setOnClickListener(new View.OnClickListener() { 105 @Override 106 public void onClick(View v) { 107 storeVoicemail(); 108 } 109 110 }); 111 } 112 113 private void storeVoicemail() { 114 try { 115 Pair<Voicemail, Uri> newVoicemail = new Pair<Voicemail, Uri>( 116 buildVoicemailObjectFromUiElements(), mRecordingUri); 117 new InsertVoicemailTask().execute(newVoicemail); 118 } catch (ParseException e) { 119 handleError(e); 120 } 121 } 122 123 private Voicemail buildVoicemailObjectFromUiElements() throws ParseException { 124 String sender = mSenderNumber.getText().toString(); 125 String dateStr = mTime.getText().toString(); 126 String durationStr = mDuration.getText().toString(); 127 String mimeType = mMimeType.getText().toString(); 128 String sourcePackageName = mProviderPackage.getText().toString(); 129 long time = DATE_FORMATTER.parse(dateStr.trim()).getTime(); 130 long duration = durationStr.length() != 0 ? Long.parseLong(durationStr) : 0; 131 return VoicemailImpl.createForInsertion(time, sender) 132 .setDuration(duration) 133 .setSourcePackage(sourcePackageName) 134 .build(); 135 } 136 137 @Override 138 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 139 super.onActivityResult(requestCode, resultCode, data); 140 switch (requestCode) { 141 case REQUEST_CODE_RECORDING: 142 handleRecordingResult(resultCode, data); 143 break; 144 default: 145 logger.e("onActivityResult: Unexpected requestCode: " + requestCode); 146 } 147 } 148 149 @Override 150 protected Dialog onCreateDialog(int id, Bundle bundle) { 151 return mDialogHelper.handleOnCreateDialog(id, bundle); 152 } 153 154 /** Set default values in the display */ 155 private void setDefaultValues() { 156 // Set time to current time. 157 mTime.setText(DATE_FORMATTER.format(new Date())); 158 159 // Set provider package to this app's package. 160 mProviderPackage.setText(getPackageName()); 161 } 162 163 private void startRecording() { 164 Intent recordingIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); 165 startActivityForResult(recordingIntent, REQUEST_CODE_RECORDING); 166 } 167 168 private void handleRecordingResult(int resultCode, Intent data) { 169 if (resultCode != RESULT_OK) { 170 handleError(new Exception("Failed to do recording. Error Code: " + resultCode)); 171 } 172 173 Uri uri = data.getData(); 174 logger.d("Received recording URI: " + uri); 175 if (uri != null) { 176 mRecordingUri = uri; 177 mMimeType.setText(getContentResolver().getType(uri)); 178 } 179 } 180 181 private void handleError(Exception e) { 182 mDialogHelper.showErrorMessageDialog(R.string.voicemail_store_error, e); 183 } 184 185 /** 186 * An async task that inserts a new voicemail record using a background thread. 187 * The tasks accepts a pair of voicemail object and the recording Uri as the param. 188 * The result returned is the error exception, if any, encountered during the operation. 189 */ 190 private class InsertVoicemailTask extends AsyncTask<Pair<Voicemail, Uri>, Void, Exception> { 191 @Override 192 protected Exception doInBackground(Pair<Voicemail, Uri>... params) { 193 if (params.length > 0) { 194 try { 195 insertVoicemail(params[0].first, params[0].second); 196 } catch (IOException e) { 197 return e; 198 } 199 } 200 return null; 201 } 202 203 private void insertVoicemail(Voicemail voicemail, Uri recordingUri) throws IOException { 204 InputStream inputAudioStream = recordingUri == null ? null : 205 getContentResolver().openInputStream(recordingUri); 206 Uri newVoicemailUri = mVoicemailProviderHelper.insert(voicemail); 207 logger.i("Inserted new voicemail URI: " + newVoicemailUri); 208 if (inputAudioStream != null) { 209 try { 210 mVoicemailProviderHelper.setVoicemailContent(newVoicemailUri, inputAudioStream, 211 getContentResolver().getType(recordingUri)); 212 } finally { 213 CloseUtils.closeQuietly(inputAudioStream); 214 } 215 } 216 } 217 218 @Override 219 protected void onPostExecute(Exception error) { 220 if (error == null) { 221 // No error - done. 222 finish(); 223 } else { 224 handleError(error); 225 } 226 } 227 228 } 229 } 230