diff --git a/app/build.gradle b/app/build.gradle
index 8603b1e..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 {
@@ -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
}
}
@@ -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.75' // 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..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;
@@ -37,8 +36,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 d897f3f..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
@@ -14,11 +14,11 @@ 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.provider.DocumentsContract;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneStateListener;
@@ -28,7 +28,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;
@@ -48,18 +47,18 @@ 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.FileDescriptor;
+import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.nio.ShortBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
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
};
@@ -74,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();
@@ -154,6 +154,67 @@ public class RecordingActivity extends AppCompatActivity {
}
}
+ public class OnFlyEncoding implements Encoder {
+ Uri targetUri;
+ Encoder e;
+ ParcelFileDescriptor fd;
+ FileDescriptor out;
+ String s;
+
+ public OnFlyEncoding(Context context, Uri targetUri, EncoderInfo info) {
+ this.targetUri = targetUri;
+
+ s = targetUri.getScheme();
+ if (s.startsWith(ContentResolver.SCHEME_CONTENT)) {
+ 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)) {
+ 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");
+ }
+
+ 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 (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ fd = null;
+ }
+ }
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(((MainApplication) getApplication()).getUserTheme());
@@ -175,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()) {
@@ -210,16 +275,6 @@ 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;
- }
- samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0);
- samplesUpdateStereo = samplesUpdate * MainApplication.getChannels(this);
-
updateBufferSize(false);
loadSamples();
@@ -259,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
@@ -302,7 +362,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);
@@ -310,7 +370,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;
@@ -353,7 +413,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();
}
}
@@ -388,22 +448,28 @@ 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() {
if (thread != null) {
- thread.interrupt();
+ interrupt.set(true);
thread = null;
}
pitch.stop();
@@ -471,10 +537,17 @@ 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);
+
+ 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) + ")");
@@ -491,7 +564,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
@@ -509,8 +582,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");
@@ -538,7 +611,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);
@@ -633,36 +706,63 @@ public class RecordingActivity extends AppCompatActivity {
pitch.record();
- AudioRecord rec;
+ int[] ss = new int[]{
+ MediaRecorder.AudioSource.MIC,
+ MediaRecorder.AudioSource.DEFAULT
+ };
- 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();
+ 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 ee) {
+ Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show();
finish();
return;
}
- rec = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min * 2);
- if (rec.getState() != AudioRecord.STATE_INITIALIZED) {
- rec = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, c, Sound.DEFAULT_AUDIOFORMAT, min * 2);
- if (rec.getState() != AudioRecord.STATE_INITIALIZED) {
- Toast.makeText(RecordingActivity.this, "Unable to initialize AudioRecord", Toast.LENGTH_SHORT).show();
- finish();
- return;
- }
- }
-
- final RawSamples rs = new RawSamples(storage.getTempRecording());
- rs.open(samplesTime * MainApplication.getChannels(this));
-
- final AudioRecord recorder = rec;
final Thread old = thread;
+ final AtomicBoolean oldb = interrupt;
+
+ interrupt = new AtomicBoolean(false);
thread = new Thread(new Runnable() {
@Override
public void run() {
if (old != null) {
+ oldb.set(true);
old.interrupt();
try {
old.join();
@@ -671,12 +771,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(Process.THREAD_PRIORITY_AUDIO);
try {
long start = System.currentTimeMillis();
@@ -684,21 +779,21 @@ 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;
boolean stableRefresh = false;
- while (!Thread.currentThread().isInterrupted()) {
+ while (!interrupt.get()) {
synchronized (bufferSizeLock) {
if (buffer == null || buffer.length != bufferSize)
buffer = new short[bufferSize];
}
int readSize = recorder.read(buffer, 0, buffer.length);
- if (readSize <= 0) {
- break;
+ if (readSize < 0) {
+ return;
}
long end = System.currentTimeMillis();
@@ -706,12 +801,12 @@ 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;
- rs.write(buffer, 0, readSize);
+ e.encode(buffer, 0, readSize);
short[] dbBuf;
int dbSize;
@@ -761,6 +856,9 @@ public class RecordingActivity extends AppCompatActivity {
}
}
}
+ if (e != null) {
+ e.close();
+ }
} catch (final RuntimeException e) {
handle.post(new Runnable() {
@Override
@@ -780,8 +878,8 @@ public class RecordingActivity extends AppCompatActivity {
}
});
- if (rs != null)
- rs.close();
+ if (e != null)
+ e.close();
if (recorder != null)
recorder.release();
@@ -815,7 +913,7 @@ public class RecordingActivity extends AppCompatActivity {
samplesUpdate = this.samplesUpdate;
}
- bufferSize = samplesUpdate * MainApplication.getChannels(this);
+ bufferSize = samplesUpdate * Sound.getChannels(this);
}
}
@@ -828,7 +926,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 {
@@ -839,47 +937,22 @@ 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);
}
- 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);
@@ -892,45 +965,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() {
@@ -939,12 +973,21 @@ 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
+ storage.delete(fly.targetUri); // fly has fd, delete target manually
d.cancel();
Error(encoder.getException());
}
@@ -989,7 +1032,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..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
@@ -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, Storage.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/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/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, "");
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 692fa47..ae429bf 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -54,4 +54,8 @@
Zeige Steuerelemente im Sperrbildschirm an
App-Theme
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 f5aa603..c511770 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -54,4 +54,8 @@
Montrez les contrôles quand le téléphone est vérrouillé
Application du Theme
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 19fac03..d72cb8a 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -54,4 +54,8 @@
Mostra i controlli quando il cellulare è bloccato
Tema applicazione
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 124ea13..d6a1375 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -54,4 +54,8 @@
電話がロックされた時にコントロールを表示します
アプリケーションのテーマ
アプリケーションのテーマを設定します (ダーク / ライト)
+ 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 f5da8b3..4d36f37 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -54,4 +54,8 @@
Mostrar controles quando a tela estiver bloqueada
Tema do app
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 2c8ccd4..bb4b60e 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -54,4 +54,8 @@
Показывать панель управления когда телефон заблокирован
Тема приложения
Установить тему приложения (темная / светлая)
+ Приложение
+ Записи
+ Кодирование на лету
+ Кодирование на лету отключает редактирование и восстановление в случае ошибок
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index cb41313..8e5d5ae 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -54,4 +54,8 @@
Zobraziť ovládacie prvky na zamikacej obrazovke
Téma
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 9455cdd..1265355 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -86,4 +86,8 @@
Show controls when phone is locked
Application Theme
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 c986730..9df6d94 100644
--- a/app/src/main/res/xml/pref_general.xml
+++ b/app/src/main/res/xml/pref_general.xml
@@ -1,77 +1,86 @@
-
+
+
-
+
-
+
-
+
-
+
-
+
+
-
+
+
-
+
-
+
+
+