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
17package com.example.android.voicemail;
18
19import com.example.android.voicemail.common.core.Voicemail;
20import com.example.android.voicemail.common.core.VoicemailImpl;
21import com.example.android.voicemail.common.core.VoicemailProviderHelper;
22import com.example.android.voicemail.common.core.VoicemailProviderHelpers;
23import com.example.android.voicemail.common.inject.InjectView;
24import com.example.android.voicemail.common.inject.Injector;
25import com.example.android.voicemail.common.logging.Logger;
26import com.example.android.voicemail.common.ui.DialogHelperImpl;
27import com.example.android.voicemail.common.utils.CloseUtils;
28
29import android.app.Activity;
30import android.app.Dialog;
31import android.content.Intent;
32import android.net.Uri;
33import android.os.AsyncTask;
34import android.os.Bundle;
35import android.provider.MediaStore;
36import android.util.Pair;
37import android.view.View;
38import android.widget.Button;
39import android.widget.TextView;
40
41import java.io.IOException;
42import java.io.InputStream;
43import java.io.OutputStream;
44import java.text.ParseException;
45import java.text.SimpleDateFormat;
46import 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 */
52public 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