/* * Copyright (C) 2015 Peter Gregus for GravityBox Project (C3C076@xda) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.wrbug.gravitybox.nougat; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; import android.os.ResultReceiver; import android.util.Log; public class RecordingService extends Service { private static final String TAG = "GB:RecordingService"; public static final String ACTION_RECORDING_START = "gravitybox.intent.action.RECORDING_START"; public static final String ACTION_RECORDING_STOP = "gravitybox.intent.action.RECORDING_STOP"; public static final String ACTION_RECORDING_GET_STATUS = "gravitybox.intent.action.RECORDING_GET_STATUS"; public static final String ACTION_RECORDING_STATUS_CHANGED = "gravitybox.intent.action.RECORDING_STATUS_CHANGED"; public static final String EXTRA_RECORDING_STATUS = "recordingStatus"; public static final String EXTRA_STATUS_MESSAGE = "statusMessage"; public static final String EXTRA_AUDIO_FILENAME = "audioFileName"; public static final String EXTRA_SAMPLING_RATE = "samplingRate"; public static final int RECORDING_STATUS_IDLE = 0; public static final int RECORDING_STATUS_STARTED = 1; public static final int RECORDING_STATUS_STOPPED = 2; public static final int RECORDING_STATUS_ERROR = -1; public static final int DEFAULT_SAMPLING_RATE = 22050; private MediaRecorder mRecorder; private int mRecordingStatus = RECORDING_STATUS_IDLE; private Notification mRecordingNotif; private PendingIntent mPendingIntent; private int mSamplingRate = DEFAULT_SAMPLING_RATE; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mRecordingStatus = RECORDING_STATUS_IDLE; Notification.Builder builder = new Notification.Builder(this); builder.setContentTitle(getString(R.string.quick_settings_qr_recording)); builder.setContentText(getString(R.string.quick_settings_qr_recording_notif)); builder.setSmallIcon(R.drawable.ic_qs_qr_recording); Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_qs_qr_recording); builder.setLargeIcon(b); Intent intent = new Intent(ACTION_RECORDING_STOP); mPendingIntent = PendingIntent.getService(this, 0, intent, 0); builder.setContentIntent(mPendingIntent); mRecordingNotif = builder.build(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null && intent.getAction() != null) { if (intent.getAction().equals(ACTION_RECORDING_START)) { if (intent.hasExtra(EXTRA_SAMPLING_RATE)) { mSamplingRate = intent.getIntExtra(EXTRA_SAMPLING_RATE, DEFAULT_SAMPLING_RATE); } startRecording(); return START_STICKY; } else if (intent.getAction().equals(ACTION_RECORDING_STOP)) { stopRecording(); return START_STICKY; } else if (intent.getAction().equals(ACTION_RECORDING_GET_STATUS)) { ResultReceiver receiver = intent.getParcelableExtra("receiver"); Bundle data = new Bundle(); data.putInt(EXTRA_RECORDING_STATUS, mRecordingStatus); receiver.send(0, data); return START_STICKY; } } stopSelf(); return START_NOT_STICKY; } MediaRecorder.OnErrorListener mOnErrorListener = new MediaRecorder.OnErrorListener() { @Override public void onError(MediaRecorder mr, int what, int extra) { mRecordingStatus = RECORDING_STATUS_ERROR; String statusMessage = "Error in MediaRecorder while recording: " + what + "; " + extra; Intent i = new Intent(ACTION_RECORDING_STATUS_CHANGED); i.putExtra(EXTRA_RECORDING_STATUS, mRecordingStatus); i.putExtra(EXTRA_STATUS_MESSAGE, statusMessage); sendBroadcast(i); stopForeground(true); } }; private String prepareOutputFile() { File outputDir = new File(Environment.getExternalStorageDirectory() + "/AudioRecordings"); if (!outputDir.exists()) { if (!outputDir.mkdir()) { Log.e(TAG, "Cannot create AudioRecordings directory"); return null; } } String fileName = "AUDIO_" + new SimpleDateFormat( "yyyyMMdd_HHmmss", Locale.US).format(new Date()) + ".mp4"; return (outputDir.getAbsolutePath() + "/" + fileName); } private void startRecording() { String statusMessage = ""; String audioFileName = prepareOutputFile(); try { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mRecorder.setOutputFile(audioFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mRecorder.setAudioEncodingBitRate(96000); mRecorder.setAudioSamplingRate(mSamplingRate); mRecorder.setOnErrorListener(mOnErrorListener); mRecorder.prepare(); mRecorder.start(); mRecordingStatus = RECORDING_STATUS_STARTED; startForeground(1, mRecordingNotif); } catch (Exception e) { e.printStackTrace(); mRecordingStatus = RECORDING_STATUS_ERROR; statusMessage = e.getMessage(); } finally { Intent i = new Intent(ACTION_RECORDING_STATUS_CHANGED); i.putExtra(EXTRA_RECORDING_STATUS, mRecordingStatus); if (mRecordingStatus == RECORDING_STATUS_STARTED) { i.putExtra(EXTRA_AUDIO_FILENAME, audioFileName); } i.putExtra(EXTRA_STATUS_MESSAGE, statusMessage); sendBroadcast(i); } } private void stopRecording() { if (mRecorder == null) return; String statusMessage = ""; try { mRecorder.stop(); mRecorder.release(); mRecorder = null; mRecordingStatus = RECORDING_STATUS_STOPPED; } catch (Exception e) { e.printStackTrace(); mRecordingStatus = RECORDING_STATUS_ERROR; statusMessage = e.getMessage(); } finally { Intent i = new Intent(ACTION_RECORDING_STATUS_CHANGED); i.putExtra(EXTRA_RECORDING_STATUS, mRecordingStatus); i.putExtra(EXTRA_STATUS_MESSAGE, statusMessage); sendBroadcast(i); stopForeground(true); } } @Override public void onDestroy() { stopRecording(); super.onDestroy(); } }