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
onCreate(Bundle savedInstanceState)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 
storeVoicemail()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 
buildVoicemailObjectFromUiElements()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
onActivityResult(int requestCode, int resultCode, Intent data)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
onCreateDialog(int id, Bundle bundle)150     protected Dialog onCreateDialog(int id, Bundle bundle) {
151         return mDialogHelper.handleOnCreateDialog(id, bundle);
152     }
153 
154     /** Set default values in the display */
setDefaultValues()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 
startRecording()163     private void startRecording() {
164         Intent recordingIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
165         startActivityForResult(recordingIntent, REQUEST_CODE_RECORDING);
166     }
167 
handleRecordingResult(int resultCode, Intent data)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 
handleError(Exception e)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
doInBackground(Pair<Voicemail, Uri>.... params)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 
insertVoicemail(Voicemail voicemail, Uri recordingUri)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
onPostExecute(Exception error)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