Home | History | Annotate | Download | only in voicemail
      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