From 367fd676fba6f9a173788572ac1838e5ba322354 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 13 Dec 2017 19:26:22 +0300 Subject: [PATCH 01/16] cleanups --- .../activities/RecordingActivity.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index d897f3f..4c748ee 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -642,9 +642,9 @@ public class RecordingActivity extends AppCompatActivity { finish(); return; } - rec = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min * 2); + rec = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min); if (rec.getState() != AudioRecord.STATE_INITIALIZED) { - rec = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min * 2); + rec = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min); if (rec.getState() != AudioRecord.STATE_INITIALIZED) { Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show(); finish(); @@ -671,12 +671,7 @@ public class RecordingActivity extends AppCompatActivity { } } - android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); - int p = android.os.Process.getThreadPriority(android.os.Process.myTid()); - - if (p != android.os.Process.THREAD_PRIORITY_URGENT_AUDIO) { - Log.e(TAG, "Unable to set Thread Priority " + android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); - } + // android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); try { long start = System.currentTimeMillis(); @@ -697,8 +692,18 @@ public class RecordingActivity extends AppCompatActivity { } int readSize = recorder.read(buffer, 0, buffer.length); - if (readSize <= 0) { - break; + if (readSize < 0) { + switch (readSize) { + case AudioRecord.ERROR: + throw new RuntimeException("AudioRecord.ERROR"); + case AudioRecord.ERROR_BAD_VALUE: + throw new RuntimeException("AudioRecord.ERROR_BAD_VALUE"); + case AudioRecord.ERROR_INVALID_OPERATION: + throw new RuntimeException("AudioRecord.ERROR_INVALID_OPERATION"); + case AudioRecord.ERROR_DEAD_OBJECT: + throw new RuntimeException("AudioRecord.ERROR_DEAD_OBJECT"); + } + return; } long end = System.currentTimeMillis(); From 7916c00b42db84bd9d63bafeba3baf095f1c32f6 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 13 Dec 2017 22:05:16 +0300 Subject: [PATCH 02/16] add audio recorder helper --- .../activities/RecordingActivity.java | 60 +++++-------------- 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 4c748ee..6375e65 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -18,7 +18,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; -import android.provider.DocumentsContract; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.telephony.PhoneStateListener; @@ -28,7 +27,6 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; -import android.webkit.MimeTypeMap; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -36,6 +34,7 @@ import android.widget.Toast; import com.github.axet.androidlibrary.animations.MarginBottomAnimation; import com.github.axet.androidlibrary.sound.AudioTrack; +import com.github.axet.audiolibrary.app.AudioRecorder; import com.github.axet.audiolibrary.app.RawSamples; import com.github.axet.audiolibrary.app.Sound; import com.github.axet.audiolibrary.encoders.Encoder; @@ -48,13 +47,7 @@ import com.github.axet.audiorecorder.app.MainApplication; import com.github.axet.audiorecorder.app.Storage; import com.github.axet.audiorecorder.services.RecordingService; -import org.apache.commons.io.IOUtils; - import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.nio.ShortBuffer; public class RecordingActivity extends AppCompatActivity { @@ -210,13 +203,8 @@ public class RecordingActivity extends AppCompatActivity { tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE); } - sampleRate = Integer.parseInt(shared.getString(MainApplication.PREFERENCE_RATE, "")); - sampleRate = Sound.getValidRecordRate(MainApplication.getInMode(this), sampleRate); - if (sampleRate == -1) { - Toast.makeText(this, "Unable to initailze audio", Toast.LENGTH_SHORT).show(); - finish(); - return; - } + sampleRate = AudioRecorder.getSampleRate(this); + samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0); samplesUpdateStereo = samplesUpdate * MainApplication.getChannels(this); @@ -633,29 +621,22 @@ public class RecordingActivity extends AppCompatActivity { pitch.record(); - AudioRecord rec; - - int c = MainApplication.getInMode(RecordingActivity.this); - int min = AudioRecord.getMinBufferSize(sampleRate, c, Sound.DEFAULT_AUDIOFORMAT); - if (min <= 0) { - Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord: Bad audio values", Toast.LENGTH_SHORT).show(); - finish(); - return; - } - rec = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min); - if (rec.getState() != AudioRecord.STATE_INITIALIZED) { - rec = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min); - if (rec.getState() != AudioRecord.STATE_INITIALIZED) { - Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show(); - finish(); - return; - } - } + int[] ss = new int[]{ + MediaRecorder.AudioSource.MIC, + MediaRecorder.AudioSource.DEFAULT + }; final RawSamples rs = new RawSamples(storage.getTempRecording()); rs.open(samplesTime * MainApplication.getChannels(this)); - final AudioRecord recorder = rec; + final AudioRecord recorder; + try { + recorder = AudioRecorder.createAudioRecorder(this, sampleRate, ss, 0); + } catch (RuntimeException e) { + Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show(); + finish(); + return; + } final Thread old = thread; @@ -693,16 +674,7 @@ public class RecordingActivity extends AppCompatActivity { int readSize = recorder.read(buffer, 0, buffer.length); if (readSize < 0) { - switch (readSize) { - case AudioRecord.ERROR: - throw new RuntimeException("AudioRecord.ERROR"); - case AudioRecord.ERROR_BAD_VALUE: - throw new RuntimeException("AudioRecord.ERROR_BAD_VALUE"); - case AudioRecord.ERROR_INVALID_OPERATION: - throw new RuntimeException("AudioRecord.ERROR_INVALID_OPERATION"); - case AudioRecord.ERROR_DEAD_OBJECT: - throw new RuntimeException("AudioRecord.ERROR_DEAD_OBJECT"); - } + AudioRecorder.throwError(readSize); return; } long end = System.currentTimeMillis(); From 4c320551be9bf616716dbd37ccae987edde45f4e Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 13 Dec 2017 22:19:28 +0300 Subject: [PATCH 03/16] cleanups --- .../activities/RecordingActivity.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 6375e65..1d40050 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -34,7 +34,6 @@ import android.widget.Toast; import com.github.axet.androidlibrary.animations.MarginBottomAnimation; import com.github.axet.androidlibrary.sound.AudioTrack; -import com.github.axet.audiolibrary.app.AudioRecorder; import com.github.axet.audiolibrary.app.RawSamples; import com.github.axet.audiolibrary.app.Sound; import com.github.axet.audiolibrary.encoders.Encoder; @@ -203,10 +202,10 @@ public class RecordingActivity extends AppCompatActivity { tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE); } - sampleRate = AudioRecorder.getSampleRate(this); + sampleRate = Sound.getSampleRate(this); samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0); - samplesUpdateStereo = samplesUpdate * MainApplication.getChannels(this); + samplesUpdateStereo = samplesUpdate * Sound.getChannels(this); updateBufferSize(false); @@ -290,7 +289,7 @@ public class RecordingActivity extends AppCompatActivity { } RawSamples rs = new RawSamples(f); - samplesTime = rs.getSamples() / MainApplication.getChannels(this); + samplesTime = rs.getSamples() / Sound.getChannels(this); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); @@ -298,7 +297,7 @@ public class RecordingActivity extends AppCompatActivity { int count = pitch.getMaxPitchCount(metrics.widthPixels); short[] buf = new short[count * samplesUpdateStereo]; - long cut = samplesTime * MainApplication.getChannels(this) - buf.length; + long cut = samplesTime * Sound.getChannels(this) - buf.length; if (cut < 0) cut = 0; @@ -459,7 +458,7 @@ public class RecordingActivity extends AppCompatActivity { final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); int rate = Integer.parseInt(shared.getString(MainApplication.PREFERENCE_RATE, "")); - int m = MainApplication.getChannels(this); + int m = Sound.getChannels(this); int c = Sound.DEFAULT_AUDIOFORMAT == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1; long perSec = (c * m * rate); @@ -479,7 +478,7 @@ public class RecordingActivity extends AppCompatActivity { int playUpdate = PitchView.UPDATE_SPEED * sampleRate / 1000; RawSamples rs = new RawSamples(storage.getTempRecording()); - int len = (int) (rs.getSamples() - editSample * MainApplication.getChannels(this)); // in samples + int len = (int) (rs.getSamples() - editSample * Sound.getChannels(this)); // in samples final AudioTrack.OnPlaybackPositionUpdateListener listener = new AudioTrack.OnPlaybackPositionUpdateListener() { @Override @@ -497,8 +496,8 @@ public class RecordingActivity extends AppCompatActivity { } }; - AudioTrack.AudioBuffer buf = new AudioTrack.AudioBuffer(sampleRate, MainApplication.getOutMode(this), Sound.DEFAULT_AUDIOFORMAT, len); - rs.open(editSample * MainApplication.getChannels(this), buf.len); // len in samples + AudioTrack.AudioBuffer buf = new AudioTrack.AudioBuffer(sampleRate, Sound.getOutMode(this), Sound.DEFAULT_AUDIOFORMAT, len); + rs.open(editSample * Sound.getChannels(this), buf.len); // len in samples int r = rs.read(buf.buffer); // r in samples if (r != buf.len) throw new RuntimeException("unable to read data"); @@ -526,7 +525,7 @@ public class RecordingActivity extends AppCompatActivity { return; RawSamples rs = new RawSamples(storage.getTempRecording()); - rs.trunk((editSample + samplesUpdate) * MainApplication.getChannels(this)); + rs.trunk((editSample + samplesUpdate) * Sound.getChannels(this)); rs.close(); edit(false, true); @@ -627,11 +626,11 @@ public class RecordingActivity extends AppCompatActivity { }; final RawSamples rs = new RawSamples(storage.getTempRecording()); - rs.open(samplesTime * MainApplication.getChannels(this)); + rs.open(samplesTime * Sound.getChannels(this)); final AudioRecord recorder; try { - recorder = AudioRecorder.createAudioRecorder(this, sampleRate, ss, 0); + recorder = Sound.createAudioRecorder(this, sampleRate, ss, 0); } catch (RuntimeException e) { Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show(); finish(); @@ -674,7 +673,7 @@ public class RecordingActivity extends AppCompatActivity { int readSize = recorder.read(buffer, 0, buffer.length); if (readSize < 0) { - AudioRecorder.throwError(readSize); + Sound.throwError(readSize); return; } long end = System.currentTimeMillis(); @@ -683,7 +682,7 @@ public class RecordingActivity extends AppCompatActivity { start = end; - int samples = readSize / MainApplication.getChannels(RecordingActivity.this); + int samples = readSize / Sound.getChannels(RecordingActivity.this); if (stableRefresh || diff >= samples) { stableRefresh = true; @@ -792,7 +791,7 @@ public class RecordingActivity extends AppCompatActivity { samplesUpdate = this.samplesUpdate; } - bufferSize = samplesUpdate * MainApplication.getChannels(this); + bufferSize = samplesUpdate * Sound.getChannels(this); } } @@ -816,7 +815,7 @@ public class RecordingActivity extends AppCompatActivity { } EncoderInfo getInfo() { - final int channels = MainApplication.getChannels(this); + final int channels = Sound.getChannels(this); final int bps = Sound.DEFAULT_AUDIOFORMAT == AudioFormat.ENCODING_PCM_16BIT ? 16 : 8; return new EncoderInfo(channels, sampleRate, bps); } From 96d7496c8b7970bfb88c47568d38f46c9d352a99 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 Dec 2017 13:28:18 +0300 Subject: [PATCH 04/16] cleanups --- .../github/axet/audiorecorder/activities/RecordingActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 1d40050..79387c0 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -673,7 +673,6 @@ public class RecordingActivity extends AppCompatActivity { int readSize = recorder.read(buffer, 0, buffer.length); if (readSize < 0) { - Sound.throwError(readSize); return; } long end = System.currentTimeMillis(); From e251fbaa8b3d3c49806507657242d8af6c7d16e2 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 Dec 2017 13:53:49 +0300 Subject: [PATCH 05/16] cleanups --- app/build.gradle | 2 +- .../axet/audiorecorder/activities/MainActivity.java | 2 -- .../audiorecorder/activities/RecordingActivity.java | 2 +- .../audiorecorder/activities/SettingsActivity.java | 10 ++-------- .../com/github/axet/audiorecorder/app/Storage.java | 8 ++++---- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8603b1e..3ed5df5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,5 +55,5 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' - compile 'com.github.axet:android-audio-library:1.0.70' // compile project(':android-audio-library') + compile 'com.github.axet:android-audio-library:1.0.71' // compile project(':android-audio-library') } diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java index 123e952..708f993 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java @@ -37,8 +37,6 @@ import com.github.axet.audiorecorder.services.RecordingService; public class MainActivity extends AppCompatActivity { public final static String TAG = MainActivity.class.getSimpleName(); - public static final String[] PERMISSIONS = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; - FloatingActionButton fab; Handler handler = new Handler(); diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 79387c0..5737a0a 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -964,7 +964,7 @@ public class RecordingActivity extends AppCompatActivity { finish(); } }); - builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java index 207fc85..d5ba33a 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java @@ -26,6 +26,7 @@ import android.widget.ProgressBar; import android.widget.Toast; import com.github.axet.androidlibrary.widgets.NameFormatPreferenceCompat; +import com.github.axet.androidlibrary.widgets.OpenFileDialog; import com.github.axet.androidlibrary.widgets.SilencePreferenceCompat; import com.github.axet.androidlibrary.widgets.StoragePathPreferenceCompat; import com.github.axet.androidlibrary.widgets.ThemeUtils; @@ -53,8 +54,6 @@ import java.util.List; */ public class SettingsActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback { - public static final String[] PERMISSIONS = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; - public static final int RESULT_STORAGE = 1; Handler handler = new Handler(); @@ -178,11 +177,6 @@ public class SettingsActivity extends AppCompatActivity implements SharedPrefere || GeneralPreferenceFragment.class.getName().equals(fragmentName); } - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(MainApplication.PREFERENCE_THEME)) { @@ -261,7 +255,7 @@ public class SettingsActivity extends AppCompatActivity implements SharedPrefere StoragePathPreferenceCompat s = (StoragePathPreferenceCompat) pm.findPreference(MainApplication.PREFERENCE_STORAGE); s.setStorage(new Storage(getContext())); - s.setPermissionsDialog(this, PERMISSIONS, RESULT_STORAGE); + s.setPermissionsDialog(this, OpenFileDialog.PERMISSIONS_RW, RESULT_STORAGE); if (Build.VERSION.SDK_INT >= 21) s.setStorageAccessFramework(this, RESULT_STORAGE); } diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java b/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java index 5b7c72d..26f32e3 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java @@ -12,10 +12,6 @@ import java.util.Date; public class Storage extends com.github.axet.audiolibrary.app.Storage { - public Storage(Context context) { - super(context); - } - public static String getFormatted(String format, Date date) { format = format.replaceAll("%s", SIMPLE.format(date)); format = format.replaceAll("%I", ISO8601.format(date)); @@ -23,6 +19,10 @@ public class Storage extends com.github.axet.audiolibrary.app.Storage { return format; } + public Storage(Context context) { + super(context); + } + public Uri getNewFile() { SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, ""); From 3895b2b012308547656ea2643d5c0b04a68f9421 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 Dec 2017 14:05:15 +0300 Subject: [PATCH 06/16] cleanups --- .../github/axet/audiorecorder/activities/SettingsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java index d5ba33a..1907630 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java @@ -255,7 +255,7 @@ public class SettingsActivity extends AppCompatActivity implements SharedPrefere StoragePathPreferenceCompat s = (StoragePathPreferenceCompat) pm.findPreference(MainApplication.PREFERENCE_STORAGE); s.setStorage(new Storage(getContext())); - s.setPermissionsDialog(this, OpenFileDialog.PERMISSIONS_RW, RESULT_STORAGE); + s.setPermissionsDialog(this, Storage.PERMISSIONS_RW, RESULT_STORAGE); if (Build.VERSION.SDK_INT >= 21) s.setStorageAccessFramework(this, RESULT_STORAGE); } From 4ac0d4f6639b38b3eecac99f92e3bff5f7671fb9 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sat, 16 Dec 2017 20:33:41 +0300 Subject: [PATCH 07/16] add cats --- app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values-ja/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 2 + app/src/main/res/values-ru/strings.xml | 2 + app/src/main/res/values-sk/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/pref_general.xml | 135 +++++++++++---------- 9 files changed, 85 insertions(+), 66 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 692fa47..9a7551c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -54,4 +54,6 @@ Zeige Steuerelemente im Sperrbildschirm an App-Theme Wähle App-Theme (dunkel / hell) + Application + Recordings diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f5aa603..670378b 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -54,4 +54,6 @@ Montrez les contrôles quand le téléphone est vérrouillé Application du Theme Appliquer le théme (Sombre | Blanc) + Application + Recordings diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 19fac03..00a720f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -54,4 +54,6 @@ Mostra i controlli quando il cellulare è bloccato Tema applicazione Imposta il tema dell'applicazione (scuro / chiaro) + Application + Recordings diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 124ea13..73fa040 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -54,4 +54,6 @@ 電話がロックされた時にコントロールを表示します アプリケーションのテーマ アプリケーションのテーマを設定します (ダーク / ライト) + Application + Recordings diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index f5da8b3..6eb3c6f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -54,4 +54,6 @@ Mostrar controles quando a tela estiver bloqueada Tema do app Definir o tema (claro ou escuro) + Application + Recordings diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 2c8ccd4..3bd66bc 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -54,4 +54,6 @@ Показывать панель управления когда телефон заблокирован Тема приложения Установить тему приложения (темная / светлая) + Application + Recordings diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index cb41313..a687586 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -54,4 +54,6 @@ Zobraziť ovládacie prvky na zamikacej obrazovke Téma Farebná téma aplikácie (svetlá / tmavá) + Application + Recordings diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9455cdd..5ba5983 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -86,4 +86,6 @@ Show controls when phone is locked Application Theme Set application theme (dark / light) + Application + Recordings diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index c986730..6aa3407 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -1,77 +1,80 @@ - + + - + - + - + - + + - + + - + - - - + + + From f224464449dd3660a0691635c9174dbffee79afc Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sat, 16 Dec 2017 20:34:00 +0300 Subject: [PATCH 08/16] add cats --- app/src/main/res/values-ru/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3bd66bc..b1eb204 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -54,6 +54,6 @@ Показывать панель управления когда телефон заблокирован Тема приложения Установить тему приложения (темная / светлая) - Application - Recordings + Приложение + Записи From 397145023e1372047a51e61d1aaf194067866db4 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Mon, 18 Dec 2017 22:22:29 +0300 Subject: [PATCH 09/16] cleanups --- .../com/github/axet/audiorecorder/activities/MainActivity.java | 1 - .../github/axet/audiorecorder/activities/RecordingActivity.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java index 708f993..0d87d3f 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java @@ -1,6 +1,5 @@ package com.github.axet.audiorecorder.activities; -import android.Manifest; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 5737a0a..a242097 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -659,7 +659,7 @@ public class RecordingActivity extends AppCompatActivity { int samplesTimeCount = 0; // how many samples we need to update 'samples'. time clock. every 1000ms. - int samplesTimeUpdate = 1000 / 1000 * sampleRate; + int samplesTimeUpdate = 1000 * sampleRate / 1000; short[] buffer = null; From 4d86d26c030f03b739ba9468268be05b3c718e04 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 29 Dec 2017 20:42:51 +0300 Subject: [PATCH 10/16] cleanups --- .../axet/audiorecorder/activities/RecordingActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index a242097..a274e45 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -52,6 +52,8 @@ import java.nio.ShortBuffer; public class RecordingActivity extends AppCompatActivity { public static final String TAG = RecordingActivity.class.getSimpleName(); + public static final int RESULT_START = 1; + public static final String[] PERMISSIONS = new String[]{ Manifest.permission.RECORD_AUDIO }; @@ -340,7 +342,7 @@ public class RecordingActivity extends AppCompatActivity { // start once if (start) { start = false; - if (Storage.permitted(this, PERMISSIONS, 1)) { + if (Storage.permitted(this, PERMISSIONS, RESULT_START)) { // audio perm startRecording(); } } @@ -803,7 +805,7 @@ public class RecordingActivity extends AppCompatActivity { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { - case 1: + case RESULT_START: if (Storage.permitted(this, permissions)) { startRecording(); } else { From 00e642b632c8359312d3781693ced9fc37a7f503 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 15:04:09 +0300 Subject: [PATCH 11/16] add encoding on fly --- .../activities/RecordingActivity.java | 227 +++++++++++------- .../audiorecorder/app/MainApplication.java | 1 + app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values-ja/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 2 + app/src/main/res/values-ru/strings.xml | 2 + app/src/main/res/values-sk/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/pref_general.xml | 6 + 11 files changed, 161 insertions(+), 89 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index a274e45..f4a757b 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -1,6 +1,7 @@ package com.github.axet.audiorecorder.activities; import android.Manifest; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; @@ -17,6 +18,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.Process; import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; @@ -148,6 +150,70 @@ public class RecordingActivity extends AppCompatActivity { } } + public class OnFlyEncoding implements Encoder { + Uri targetUri; + Encoder e; + File out; + String s; + + public OnFlyEncoding(Context context, Uri targetUri, EncoderInfo info) { + this.targetUri = targetUri; + + s = targetUri.getScheme(); + if (s.startsWith(ContentResolver.SCHEME_CONTENT)) { + out = storage.getTempEncoding(); + } else if (s.startsWith(ContentResolver.SCHEME_FILE)) { + out = Storage.getFile(targetUri); + } else { + throw new RuntimeException("unkonwn uri"); + } + + File parent = out.getParentFile(); + + if (!parent.exists() && !parent.mkdirs()) { // in case if it were manually deleted + throw new RuntimeException("Unable to create: " + parent); + } + + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); + String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, ""); + + e = Factory.getEncoder(context, ext, info, out); + } + + @Override + public void encode(short[] buf, int pos, int len) { + e.encode(buf, pos, len); + } + + @Override + public void close() { + if (e != null) { + e.close(); + e = null; + } + + if (out != null && out.exists() && out.length() > 0) { + if (Build.VERSION.SDK_INT >= 21 && s.startsWith(ContentResolver.SCHEME_CONTENT)) { // for non SCHEME_CONTENT we write directly to storage + ContentResolver resolver = getContentResolver(); + try { + Uri root = Storage.getDocumentTreeUri(targetUri); + resolver.takePersistableUriPermission(root, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + storage.move(out, root, Storage.getDocumentChildPath(targetUri)); + } catch (RuntimeException e) { + Storage.delete(out); // delete tmp encoding file + try { + storage.delete(targetUri); // delete SAF encoding file + } catch (RuntimeException ee) { + Log.d(TAG, "unable to delete target uri", ee); // ignore, not even created? + } + throw e; + } + } + out = null; + } + } + } + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(((MainApplication) getApplication()).getUserTheme()); @@ -377,17 +443,23 @@ public class RecordingActivity extends AppCompatActivity { RecordingService.startService(this, Storage.getDocumentName(targetUri), thread != null, encoder != null); - pitch.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - edit(true, true); - float x = event.getX(); - if (x < 0) - x = 0; - editSample = pitch.edit(x) * samplesUpdate; - return true; - } - }); + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); + + if (shared.getBoolean(MainApplication.PREFERENCE_FLY, false)) { + pitch.setOnTouchListener(null); + } else { + pitch.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + edit(true, true); + float x = event.getX(); + if (x < 0) + x = 0; + editSample = pitch.edit(x) * samplesUpdate; + return true; + } + }); + } } void stopRecording() { @@ -627,13 +699,43 @@ public class RecordingActivity extends AppCompatActivity { MediaRecorder.AudioSource.DEFAULT }; - final RawSamples rs = new RawSamples(storage.getTempRecording()); - rs.open(samplesTime * Sound.getChannels(this)); + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); + + final Encoder e; + + if (shared.getBoolean(MainApplication.PREFERENCE_FLY, false)) { + final OnFlyEncoding fly = new OnFlyEncoding(this, targetUri, getInfo()); + e = new Encoder() { + @Override + public void encode(short[] buf, int pos, int len) { + fly.encode(buf, pos, len); + } + + @Override + public void close() { + fly.close(); + } + }; + } else { + final RawSamples rs = new RawSamples(storage.getTempRecording()); + rs.open(samplesTime * Sound.getChannels(this)); + e = new Encoder() { + @Override + public void encode(short[] buf, int pos, int len) { + rs.write(buf, pos, len); + } + + @Override + public void close() { + rs.close(); + } + }; + } final AudioRecord recorder; try { recorder = Sound.createAudioRecorder(this, sampleRate, ss, 0); - } catch (RuntimeException e) { + } catch (RuntimeException ee) { Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show(); finish(); return; @@ -653,7 +755,7 @@ public class RecordingActivity extends AppCompatActivity { } } - // android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); + android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO); try { long start = System.currentTimeMillis(); @@ -688,7 +790,7 @@ public class RecordingActivity extends AppCompatActivity { if (stableRefresh || diff >= samples) { stableRefresh = true; - rs.write(buffer, 0, readSize); + e.encode(buffer, 0, readSize); short[] dbBuf; int dbSize; @@ -738,6 +840,9 @@ public class RecordingActivity extends AppCompatActivity { } } } + if (e != null) { + e.close(); + } } catch (final RuntimeException e) { handle.post(new Runnable() { @Override @@ -757,8 +862,8 @@ public class RecordingActivity extends AppCompatActivity { } }); - if (rs != null) - rs.close(); + if (e != null) + e.close(); if (recorder != null) recorder.release(); @@ -821,42 +926,17 @@ public class RecordingActivity extends AppCompatActivity { return new EncoderInfo(channels, sampleRate, bps); } - void encoding(final Runnable run) { + void encoding(final Runnable done) { final File in = storage.getTempRecording(); - final File out; - if (!in.exists()) { + if (!in.exists() || in.length() == 0) { finish(); return; } - final String s = targetUri.getScheme(); - if (s.startsWith(ContentResolver.SCHEME_CONTENT)) { - out = storage.getTempEncoding(); - } else if (s.startsWith(ContentResolver.SCHEME_FILE)) { - out = Storage.getFile(targetUri); - } else { - throw new RuntimeException("unkonwn uri"); - } + final OnFlyEncoding fly = new OnFlyEncoding(this, targetUri, getInfo()); - File parent = out.getParentFile(); - - if (!parent.exists()) { - if (!parent.mkdirs()) { // in case if it were manually deleted - throw new RuntimeException("Unable to create: " + parent); - } - } - - EncoderInfo info = getInfo(); - - Encoder e = null; - - final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); - String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, ""); - - e = Factory.getEncoder(this, ext, info, out); - - encoder = new FileEncoder(this, in, e); + encoder = new FileEncoder(this, in, fly); RecordingService.startService(this, Storage.getDocumentName(targetUri), thread != null, encoder != null); @@ -869,45 +949,6 @@ public class RecordingActivity extends AppCompatActivity { d.setIndeterminate(false); d.show(); - final Runnable save = new Runnable() { - @Override - public void run() { - if (Build.VERSION.SDK_INT >= 21 && s.startsWith(ContentResolver.SCHEME_CONTENT)) { // for non SCHEME we write dirrectlry to storage - ContentResolver resolver = getContentResolver(); - try { - Uri root = Storage.getDocumentTreeUri(targetUri); - resolver.takePersistableUriPermission(root, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - storage.move(out, root, Storage.getDocumentChildPath(targetUri)); - } catch (RuntimeException e) { - Storage.delete(out); // delete tmp encoding file - try { - storage.delete(targetUri); // delete SAF encoding file - } catch (RuntimeException ee) { - Log.d(TAG, "unable to delete target uri", ee); // ignore, not even created? - } - Post(e); - d.cancel(); - return; - } - } - - handler.post(new Runnable() { - @Override - public void run() { - Storage.delete(in); // delete raw recording - - SharedPreferences.Editor edit = shared.edit(); - edit.putString(MainApplication.PREFERENCE_LAST, Storage.getDocumentName(targetUri)); - edit.commit(); - - run.run(); - - d.cancel(); - } - }); - } - }; - encoder.run(new Runnable() { @Override public void run() { @@ -916,12 +957,20 @@ public class RecordingActivity extends AppCompatActivity { }, new Runnable() { @Override public void run() { // success - Thread thread = new Thread(save); // network on main thread for SAF network - thread.start(); + Storage.delete(in); // delete raw recording + + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(RecordingActivity.this); + SharedPreferences.Editor edit = shared.edit(); + edit.putString(MainApplication.PREFERENCE_LAST, Storage.getDocumentName(targetUri)); + edit.commit(); + + done.run(); + + d.cancel(); } }, new Runnable() { @Override - public void run() { // done + public void run() { // or error d.cancel(); Error(encoder.getException()); } diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/MainApplication.java b/app/src/main/java/com/github/axet/audiorecorder/app/MainApplication.java index 839065d..1ab3b50 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/MainApplication.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/MainApplication.java @@ -8,6 +8,7 @@ public class MainApplication extends com.github.axet.audiolibrary.app.MainApplic public static final String PREFERENCE_CONTROLS = "controls"; public static final String PREFERENCE_TARGET = "target"; + public static final String PREFERENCE_FLY = "fly"; public int getUserTheme() { return getTheme(this, R.style.RecThemeLight, R.style.RecThemeDark); diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9a7551c..ae429bf 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -56,4 +56,6 @@ Wähle App-Theme (dunkel / hell) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 670378b..c511770 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -56,4 +56,6 @@ Appliquer le théme (Sombre | Blanc) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 00a720f..d72cb8a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -56,4 +56,6 @@ Imposta il tema dell'applicazione (scuro / chiaro) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 73fa040..d6a1375 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -56,4 +56,6 @@ アプリケーションのテーマを設定します (ダーク / ライト) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6eb3c6f..4d36f37 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -56,4 +56,6 @@ Definir o tema (claro ou escuro) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index b1eb204..bb4b60e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -56,4 +56,6 @@ Установить тему приложения (темная / светлая) Приложение Записи + Кодирование на лету + Кодирование на лету отключает редактирование и восстановление в случае ошибок diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a687586..8e5d5ae 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -56,4 +56,6 @@ Farebná téma aplikácie (svetlá / tmavá) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5ba5983..1265355 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,4 +88,6 @@ Set application theme (dark / light) Application Recordings + Encoding on Fly + Encoding on fly disable editing, and crash recovery diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 6aa3407..9df6d94 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -46,6 +46,12 @@ android:positiveButtonText="@null" android:summary="2015-12-31 22:11:34" android:title="@string/pref_nameformat_title" /> + + From bb5e6846f419c0628297e5ea036782b95c78dd76 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 15:12:27 +0300 Subject: [PATCH 12/16] fix rate --- .../axet/audiorecorder/activities/RecordingActivity.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index f4a757b..a7597d1 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -536,6 +536,13 @@ public class RecordingActivity extends AppCompatActivity { int c = Sound.DEFAULT_AUDIOFORMAT == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1; long perSec = (c * m * rate); + + String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, ""); + + if (shared.getBoolean(MainApplication.PREFERENCE_FLY, false)) { + perSec = Factory.getEncoderRate(ext, sampleRate); + } + long sec = free / perSec * 1000; state.setText(s + "\n(" + MainApplication.formatFree(this, free, sec) + ")"); From 6b62aa309a2d842f27f437d7c3644a7b692901ef Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 16:36:59 +0300 Subject: [PATCH 13/16] fix thread interruption --- app/build.gradle | 2 +- .../activities/RecordingActivity.java | 84 ++++++++++--------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3ed5df5..1236b3c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,7 +46,7 @@ android { abi { enable true reset() - include "x86", "armeabi-v7a", "mips" + include "x86", "x86_64", "armeabi-v7a", "arm64-v8a", "mips", "mips64" universalApk true } } diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index a7597d1..e02c10b 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -1,7 +1,6 @@ package com.github.axet.audiorecorder.activities; import android.Manifest; -import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; @@ -15,9 +14,9 @@ import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.preference.PreferenceManager; import android.support.v7.app.ActionBar; @@ -49,7 +48,11 @@ import com.github.axet.audiorecorder.app.Storage; import com.github.axet.audiorecorder.services.RecordingService; import java.io.File; +import java.io.FileDescriptor; +import java.io.FileNotFoundException; +import java.io.IOException; import java.nio.ShortBuffer; +import java.util.concurrent.atomic.AtomicBoolean; public class RecordingActivity extends AppCompatActivity { public static final String TAG = RecordingActivity.class.getSimpleName(); @@ -70,6 +73,7 @@ public class RecordingActivity extends AppCompatActivity { // do we need to start recording immidiatly? boolean start = true; + AtomicBoolean interrupt = new AtomicBoolean(); // nio throws ClosedByInterruptException if thread interrupted Thread thread; // lock for bufferSize final Object bufferSizeLock = new Object(); @@ -153,7 +157,8 @@ public class RecordingActivity extends AppCompatActivity { public class OnFlyEncoding implements Encoder { Uri targetUri; Encoder e; - File out; + ParcelFileDescriptor fd; + FileDescriptor out; String s; public OnFlyEncoding(Context context, Uri targetUri, EncoderInfo info) { @@ -161,19 +166,27 @@ public class RecordingActivity extends AppCompatActivity { s = targetUri.getScheme(); if (s.startsWith(ContentResolver.SCHEME_CONTENT)) { - out = storage.getTempEncoding(); + Uri root = Storage.getDocumentTreeUri(targetUri); + Uri o = storage.createFile(root, Storage.getDocumentChildPath(targetUri)); + ContentResolver resolver = context.getContentResolver(); + try { + fd = resolver.openFileDescriptor(o, "rw"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + out = fd.getFileDescriptor(); } else if (s.startsWith(ContentResolver.SCHEME_FILE)) { - out = Storage.getFile(targetUri); + File f = Storage.getFile(targetUri); + try { + fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_READ_WRITE); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + out = fd.getFileDescriptor(); } else { throw new RuntimeException("unkonwn uri"); } - File parent = out.getParentFile(); - - if (!parent.exists() && !parent.mkdirs()) { // in case if it were manually deleted - throw new RuntimeException("Unable to create: " + parent); - } - final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, ""); @@ -191,25 +204,13 @@ public class RecordingActivity extends AppCompatActivity { e.close(); e = null; } - - if (out != null && out.exists() && out.length() > 0) { - if (Build.VERSION.SDK_INT >= 21 && s.startsWith(ContentResolver.SCHEME_CONTENT)) { // for non SCHEME_CONTENT we write directly to storage - ContentResolver resolver = getContentResolver(); - try { - Uri root = Storage.getDocumentTreeUri(targetUri); - resolver.takePersistableUriPermission(root, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - storage.move(out, root, Storage.getDocumentChildPath(targetUri)); - } catch (RuntimeException e) { - Storage.delete(out); // delete tmp encoding file - try { - storage.delete(targetUri); // delete SAF encoding file - } catch (RuntimeException ee) { - Log.d(TAG, "unable to delete target uri", ee); // ignore, not even created? - } - throw e; - } + if (fd != null) { + try { + fd.close(); + } catch (IOException e) { + throw new RuntimeException(e); } - out = null; + fd = null; } } } @@ -235,9 +236,13 @@ public class RecordingActivity extends AppCompatActivity { storage = new Storage(this); sound = new Sound(this); + sampleRate = Sound.getSampleRate(this); + samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0); + samplesUpdateStereo = samplesUpdate * Sound.getChannels(this); + edit(false, false); - SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); try { if (storage.recordingPending()) { @@ -270,11 +275,6 @@ public class RecordingActivity extends AppCompatActivity { tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE); } - sampleRate = Sound.getSampleRate(this); - - samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0); - samplesUpdateStereo = samplesUpdate * Sound.getChannels(this); - updateBufferSize(false); loadSamples(); @@ -314,7 +314,12 @@ public class RecordingActivity extends AppCompatActivity { public void onClick(View v) { if (encoder != null) return; - stopRecording(getString(R.string.recording_status_encoding)); + String msg; + if (shared.getBoolean(MainApplication.PREFERENCE_FLY, false)) { + msg = getString(R.string.recording_status_recording); + } else + msg = getString(R.string.recording_status_encoding); + stopRecording(msg); try { encoding(new Runnable() { @Override @@ -464,7 +469,7 @@ public class RecordingActivity extends AppCompatActivity { void stopRecording() { if (thread != null) { - thread.interrupt(); + interrupt.set(true); thread = null; } pitch.stop(); @@ -750,6 +755,8 @@ public class RecordingActivity extends AppCompatActivity { final Thread old = thread; + interrupt = new AtomicBoolean(false); + thread = new Thread(new Runnable() { @Override public void run() { @@ -776,7 +783,7 @@ public class RecordingActivity extends AppCompatActivity { boolean stableRefresh = false; - while (!Thread.currentThread().isInterrupted()) { + while (!interrupt.get()) { synchronized (bufferSizeLock) { if (buffer == null || buffer.length != bufferSize) buffer = new short[bufferSize]; @@ -978,6 +985,7 @@ public class RecordingActivity extends AppCompatActivity { }, new Runnable() { @Override public void run() { // or error + storage.delete(fly.targetUri); // fly has fd, delete target manually d.cancel(); Error(encoder.getException()); } From de2d1f60a2e7867ee48ef4d5f5eacae638f46b7a Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 16:37:48 +0300 Subject: [PATCH 14/16] fix set interrupt --- .../github/axet/audiorecorder/activities/RecordingActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index e02c10b..3b440e3 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -754,6 +754,7 @@ public class RecordingActivity extends AppCompatActivity { } final Thread old = thread; + final AtomicBoolean oldb = interrupt; interrupt = new AtomicBoolean(false); @@ -761,6 +762,7 @@ public class RecordingActivity extends AppCompatActivity { @Override public void run() { if (old != null) { + oldb.set(true); old.interrupt(); try { old.join(); From 24dd37203b52675d54af44728a9ead1073078a77 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 16:41:28 +0300 Subject: [PATCH 15/16] enable on fly ecoding --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 1236b3c..4e81703 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,5 +55,5 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' - compile 'com.github.axet:android-audio-library:1.0.71' // compile project(':android-audio-library') + compile 'com.github.axet:android-audio-library:1.0.75' // compile project(':android-audio-library') } From 2328f1e6229fdda73f6377a8b9c6545078069594 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 31 Dec 2017 16:41:36 +0300 Subject: [PATCH 16/16] Bump version audiorecorder-3.0.61 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4e81703..4f31aea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.github.axet.audiorecorder" minSdkVersion 9 targetSdkVersion 23 // 24+ file:// unable to open - versionCode 226 - versionName "3.0.60" + versionCode 227 + versionName "3.0.61" } signingConfigs { release {