diff --git a/app/build.gradle b/app/build.gradle index 741d6a9..a675ff8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,15 +2,15 @@ apply plugin: 'com.android.application' apply plugin: 'com.github.axet.dxplugin' android { - compileSdkVersion 29 - buildToolsVersion '28.0.3' + compileSdkVersion 30 + ndkVersion "16.1.4479499" // strip debug symbols defaultConfig { applicationId "com.github.axet.audiorecorder" minSdkVersion 9 - targetSdkVersion 29 - versionCode 355 - versionName "3.4.5" + targetSdkVersion 30 + versionCode 356 + versionName "3.5.0" } signingConfigs { release { @@ -53,8 +53,7 @@ android { dependencies { testImplementation 'junit:junit:4.12' - implementation 'com.github.axet:android-library:1.33.6' - implementation ('com.github.axet:android-audio-library:1.0.180') { exclude module: 'android-library' } // implementation project(':android-audio-library') + implementation ('com.github.axet:android-audio-library:1.1.1') // implementation project(':android-audio-library') implementation ('com.github.axet:wget:1.7.0') { exclude group: 'org.json', module: 'json' } assets('com.google.android.exoplayer:exoplayer:2.7.3') { exclude group: 'com.android.support' } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 60ca36d..d2c9784 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,7 +23,7 @@ android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" android:theme="@style/Translucent"> - + 0) { - recording.dbBuffer = ShortBuffer.allocate(recording.samplesUpdateStereo); + recording.dbBuffer = new AudioTrack.SamplesBuffer(rs.info.format, recording.samplesUpdateStereo); recording.dbBuffer.put(buf, lenUpdate, diff); } } @@ -745,14 +747,14 @@ public class RecordingActivity extends AppCompatThemeActivity { int rate = Integer.parseInt(shared.getString(AudioApplication.PREFERENCE_RATE, "")); int m = Sound.getChannels(this); - int c = Sound.DEFAULT_AUDIOFORMAT == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1; + int c = RawSamples.getBytes(recording.info.format); long perSec; String ext = shared.getString(AudioApplication.PREFERENCE_ENCODING, ""); if (shared.getBoolean(AudioApplication.PREFERENCE_FLY, false)) { - perSec = Factory.getEncoderRate(ext, recording.sampleRate); + perSec = Factory.getEncoderRate(Sound.getAudioFormat(this), ext, recording.sampleRate); try { free = Storage.getFree(this, recording.targetUri); } catch (RuntimeException e) { // IllegalArgumentException @@ -780,8 +782,8 @@ public class RecordingActivity extends AppCompatThemeActivity { int playUpdate = PitchView.UPDATE_SPEED * recording.sampleRate / 1000; - RawSamples rs = new RawSamples(recording.storage.getTempRecording()); - int len = (int) (rs.getSamples() - editSample * Sound.getChannels(this)); // in samples + RawSamples rs = new RawSamples(recording.storage.getTempRecording(), recording.info); + int len = (int) (rs.getSamples() - editSample * rs.info.channels); // in samples final AudioTrack.OnPlaybackPositionUpdateListener listener = new AudioTrack.OnPlaybackPositionUpdateListener() { @Override @@ -799,8 +801,8 @@ public class RecordingActivity extends AppCompatThemeActivity { } }; - AudioTrack.AudioBuffer buf = new AudioTrack.AudioBuffer(recording.sampleRate, Sound.getOutMode(this), Sound.DEFAULT_AUDIOFORMAT, len); - rs.open(editSample * Sound.getChannels(this), buf.len); // len in samples + AudioTrack.AudioBuffer buf = new AudioTrack.AudioBuffer(recording.sampleRate, Sound.getOutMode(this), rs.info.format, len); + rs.open(editSample * rs.info.channels, 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"); @@ -827,8 +829,8 @@ public class RecordingActivity extends AppCompatThemeActivity { if (editSample == -1) return; - RawSamples rs = new RawSamples(recording.storage.getTempRecording()); - rs.trunk((editSample + recording.samplesUpdate) * Sound.getChannels(this)); + RawSamples rs = new RawSamples(recording.storage.getTempRecording(), recording.info); + rs.trunk((editSample + recording.samplesUpdate) * rs.info.channels); rs.close(); edit(false, true); @@ -924,8 +926,28 @@ public class RecordingActivity extends AppCompatThemeActivity { editor.commit(); } - void startRecording() { + boolean startRecording() { try { + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); + String source = shared.getString(AudioApplication.PREFERENCE_SOURCE, getString(R.string.source_mic)); + int user; + if (source.equals(getString(R.string.source_raw))) { + if (Sound.isUnprocessedSupported(this)) + user = MediaRecorder.AudioSource.UNPROCESSED; + else + user = MediaRecorder.AudioSource.VOICE_RECOGNITION; + } else if (source.equals(this.getString(R.string.source_internal))) { + user = Sound.SOURCE_INTERNAL_AUDIO; + } else { + user = MediaRecorder.AudioSource.MIC; + } + if (user == Sound.SOURCE_INTERNAL_AUDIO && !recording.sound.permitted()) { + Sound.showInternalAudio(this, RESULT_INTERNAL); + return false; + } + + recording.startRecording(user); + edit(false, true); pitch.setOnTouchListener(null); @@ -938,13 +960,13 @@ public class RecordingActivity extends AppCompatThemeActivity { headset(true, true); - recording.startRecording(); - RecordingService.startService(this, Storage.getName(this, recording.targetUri), true, duration); ControlsService.hideIcon(this); + return true; } catch (RuntimeException e) { Toast.Error(RecordingActivity.this, e); finish(); + return false; } } @@ -970,6 +992,23 @@ public class RecordingActivity extends AppCompatThemeActivity { Toast.makeText(this, R.string.not_permitted, Toast.LENGTH_SHORT).show(); finish(); } + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode) { + case RESULT_INTERNAL: + if (resultCode == RESULT_OK) { + recording.sound.onActivityResult(data); + startRecording(); + } else { + Toast.makeText(this, R.string.not_permitted, Toast.LENGTH_SHORT).show(); + finish(); + } + break; } } @@ -1042,7 +1081,7 @@ public class RecordingActivity extends AppCompatThemeActivity { } else { done.run(); } - encoding = EncodingService.startEncoding(this, in, recording.targetUri, recording.getInfo()); + encoding = EncodingService.startEncoding(this, in, recording.targetUri, recording.info); } @Override 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 f3a0944..4252431 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 @@ -99,7 +99,7 @@ public class SettingsActivity extends AppCompatSettingsThemeActivity implements storage.migrateLocalStorageDialog(this); if (key.equals(AudioApplication.PREFERENCE_RATE)) { int sampleRate = Integer.parseInt(sharedPreferences.getString(AudioApplication.PREFERENCE_RATE, "")); - if (sampleRate != Sound.getValidRecordRate(Sound.getInMode(this), sampleRate)) + if (sampleRate != Sound.getValidRecordRate(Sound.getAudioFormat(this), Sound.getInMode(this), sampleRate)) Toast.Text(this, "Not supported Hz"); } } @@ -163,6 +163,7 @@ public class SettingsActivity extends AppCompatSettingsThemeActivity implements bindPreferenceSummaryToValue(pm.findPreference(AudioApplication.PREFERENCE_CHANNELS)); bindPreferenceSummaryToValue(pm.findPreference(AudioApplication.PREFERENCE_FORMAT)); bindPreferenceSummaryToValue(pm.findPreference(AudioApplication.PREFERENCE_VOLUME)); + bindPreferenceSummaryToValue(pm.findPreference(AudioApplication.PREFERENCE_AUDIOFORMAT)); StoragePathPreferenceCompat s = (StoragePathPreferenceCompat) pm.findPreference(AudioApplication.PREFERENCE_STORAGE); s.setStorage(new Storage(getContext())); @@ -189,6 +190,10 @@ public class SettingsActivity extends AppCompatSettingsThemeActivity implements return true; } }); + + Preference af = pm.findPreference(AudioApplication.PREFERENCE_AUDIOFORMAT); + if (Build.VERSION.SDK_INT < 23 && af != null) + af.setVisible(false); } @Override diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/EncodingStorage.java b/app/src/main/java/com/github/axet/audiorecorder/app/EncodingStorage.java index 82f760e..1cf7ac9 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/EncodingStorage.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/EncodingStorage.java @@ -140,7 +140,7 @@ public class EncodingStorage extends HashMap { for (File in : keySet()) { EncodingStorage.Info info = get(in); final OnFlyEncoding fly = new OnFlyEncoding(this.storage, info.targetUri, info.info); - encoder = new FileEncoder(storage.getContext(), in, fly); + encoder = new FileEncoder(storage.getContext(), in, info.info, fly); filters(encoder, info.info); encoding(encoder, fly, info.info, new Runnable() { @Override @@ -208,7 +208,7 @@ public class EncodingStorage extends HashMap { public void encoding(File in, Uri targetUri, RawSamples.Info info) { OnFlyEncoding fly = new OnFlyEncoding(storage, targetUri, info); - encoder = new FileEncoder(storage.getContext(), in, fly); + encoder = new FileEncoder(storage.getContext(), in, info, fly); filters(encoder, info); encoding(encoder, fly, info, new Runnable() { @Override @@ -220,7 +220,7 @@ public class EncodingStorage extends HashMap { public void saveAsWAV(File in, File out, RawSamples.Info info) { OnFlyEncoding fly = new OnFlyEncoding(storage, out, info); - encoder = new FileEncoder(storage.getContext(), in, fly); + encoder = new FileEncoder(storage.getContext(), in, info, fly); encoding(encoder, fly, info, new Runnable() { @Override public void run() { diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/RecordingStorage.java b/app/src/main/java/com/github/axet/audiorecorder/app/RecordingStorage.java index 693affa..fd6e6ef 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/RecordingStorage.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/RecordingStorage.java @@ -1,14 +1,18 @@ package com.github.axet.audiorecorder.app; +import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; +import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.net.Uri; +import android.os.Build; import android.os.Handler; import android.os.PowerManager; import android.os.Process; +import com.github.axet.androidlibrary.sound.AudioTrack; import com.github.axet.audiolibrary.app.RawSamples; import com.github.axet.audiolibrary.app.Sound; import com.github.axet.audiolibrary.encoders.Encoder; @@ -16,8 +20,18 @@ import com.github.axet.audiolibrary.encoders.OnFlyEncoding; import com.github.axet.audiorecorder.BuildConfig; import com.github.axet.audiorecorder.R; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.json.JSONException; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; import java.nio.ShortBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; public class RecordingStorage { @@ -35,7 +49,7 @@ public class RecordingStorage { public Sound sound; public Storage storage; - public Encoder e; + public Encoder e; // recording encoder (onfly or raw data) public AtomicBoolean interrupt = new AtomicBoolean(); // nio throws ClosedByInterruptException if thread interrupted public Thread thread; @@ -46,12 +60,13 @@ public class RecordingStorage { public int samplesUpdateStereo; // samplesUpdate * number of channels public Uri targetUri = null; // output target file 2016-01-01 01.01.01.wav public long samplesTime; // how many samples passed for current recording, stereo = samplesTime * 2 + public RawSamples.Info info; - public ShortBuffer dbBuffer = null; // PinchView samples buffer + public AudioTrack.SamplesBuffer dbBuffer = null; // PinchView samples buffer public int pitchTime; // screen width - public RecordingStorage(Context context, int pitchTime, Uri targetUri) { + public RecordingStorage(Context context, int format, int pitchTime, Uri targetUri) { this.context = context; this.pitchTime = pitchTime; this.targetUri = targetUri; @@ -60,36 +75,26 @@ public class RecordingStorage { sampleRate = Sound.getSampleRate(context); samplesUpdate = (int) (pitchTime * sampleRate / 1000f); samplesUpdateStereo = samplesUpdate * Sound.getChannels(context); + info = new RawSamples.Info(format, sampleRate, Sound.getChannels(context)); } - public void startRecording() { - sound.silent(); - + public void startRecording(int source) { final SharedPreferences shared = android.preference.PreferenceManager.getDefaultSharedPreferences(context); - int user; - - if (shared.getString(AudioApplication.PREFERENCE_SOURCE, context.getString(R.string.source_mic)).equals(context.getString(R.string.source_raw))) { - if (Sound.isUnprocessedSupported(context)) - user = MediaRecorder.AudioSource.UNPROCESSED; - else - user = MediaRecorder.AudioSource.VOICE_RECOGNITION; - } else { - user = MediaRecorder.AudioSource.MIC; - } + sound.silent(); int[] ss = new int[]{ - user, + source, MediaRecorder.AudioSource.MIC, MediaRecorder.AudioSource.DEFAULT }; if (shared.getBoolean(AudioApplication.PREFERENCE_FLY, false)) { - final OnFlyEncoding fly = new OnFlyEncoding(storage, targetUri, getInfo()); if (e == null) { // do not recreate encoder if on-fly mode enabled + final OnFlyEncoding fly = new OnFlyEncoding(storage, targetUri, info); e = new Encoder() { @Override - public void encode(short[] buf, int pos, int len) { + public void encode(AudioTrack.SamplesBuffer buf, int pos, int len) { fly.encode(buf, pos, len); } @@ -100,11 +105,11 @@ public class RecordingStorage { }; } } else { - final RawSamples rs = new RawSamples(storage.getTempRecording()); - rs.open(samplesTime * Sound.getChannels(context)); + final RawSamples rs = new RawSamples(storage.getTempRecording(), info); + rs.open(samplesTime * rs.info.channels); e = new Encoder() { @Override - public void encode(short[] buf, int pos, int len) { + public void encode(AudioTrack.SamplesBuffer buf, int pos, int len) { rs.write(buf, pos, len); } @@ -115,7 +120,7 @@ public class RecordingStorage { }; } - final AudioRecord recorder = Sound.createAudioRecorder(context, sampleRate, ss, 0); + final AudioRecord recorder = sound.createAudioRecorder(info.format, sampleRate, ss, 0); final Thread old = thread; final AtomicBoolean oldb = interrupt; @@ -154,17 +159,34 @@ public class RecordingStorage { int samplesTimeCount = 0; final int samplesTimeUpdate = 1000 * sampleRate / 1000; // how many samples we need to update 'samples'. time clock. every 1000ms. - short[] buffer = null; + AudioTrack.SamplesBuffer buffer = null; boolean stableRefresh = false; while (!interrupt.get()) { synchronized (bufferSizeLock) { - if (buffer == null || buffer.length != bufferSize) - buffer = new short[bufferSize]; + if (buffer == null || buffer.size() != bufferSize) + buffer = new AudioTrack.SamplesBuffer(info.format, bufferSize); + } + + int readSize = -1; + switch (buffer.format) { + case AudioFormat.ENCODING_PCM_8BIT: + break; + case AudioFormat.ENCODING_PCM_16BIT: + readSize = recorder.read(buffer.shorts, 0, buffer.shorts.length); + case Sound.ENCODING_PCM_24BIT_PACKED: + break; + case Sound.ENCODING_PCM_32BIT: + break; + case AudioFormat.ENCODING_PCM_FLOAT: + if (Build.VERSION.SDK_INT >= 23) + readSize = recorder.read(buffer.floats, 0, buffer.floats.length, AudioRecord.READ_BLOCKING); + break; + default: + throw new RuntimeException("Unknown format"); } - int readSize = recorder.read(buffer, 0, buffer.length); if (readSize < 0) return; long now = System.currentTimeMillis(); @@ -178,18 +200,18 @@ public class RecordingStorage { e.encode(buffer, 0, readSize); - short[] dbBuf; + AudioTrack.SamplesBuffer dbBuf; int dbSize; int readSizeUpdate; if (dbBuffer != null) { - ShortBuffer bb = ShortBuffer.allocate(dbBuffer.position() + readSize); + AudioTrack.SamplesBuffer bb = new AudioTrack.SamplesBuffer(info.format, dbBuffer.position + readSize); dbBuffer.flip(); bb.put(dbBuffer); bb.put(buffer, 0, readSize); - dbBuf = new short[bb.position()]; - dbSize = dbBuf.length; + dbBuf = new AudioTrack.SamplesBuffer(info.format, bb.position); + dbSize = dbBuf.count; bb.flip(); - bb.get(dbBuf, 0, dbBuf.length); + bb.get(dbBuf, 0, dbBuf.count); } else { dbBuf = buffer; dbSize = readSize; @@ -204,7 +226,7 @@ public class RecordingStorage { } int readSizeLen = dbSize - readSizeUpdate; if (readSizeLen > 0) { - dbBuffer = ShortBuffer.allocate(readSizeLen); + dbBuffer = new AudioTrack.SamplesBuffer(info.format, readSizeLen); dbBuffer.put(dbBuf, readSizeUpdate, readSizeLen); } else { dbBuffer = null; @@ -277,10 +299,6 @@ public class RecordingStorage { sound.unsilent(); } - public RawSamples.Info getInfo() { - return new RawSamples.Info(sampleRate, Sound.getChannels(context)); - } - // calcuale buffer length dynamically, this way we can reduce thread cycles when activity in background // or phone screen is off. public void updateBufferSize(boolean pause) { diff --git a/app/src/main/java/com/github/axet/audiorecorder/services/BluetoothReceiver.java b/app/src/main/java/com/github/axet/audiorecorder/services/BluetoothReceiver.java index 3a11598..ac4c380 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/services/BluetoothReceiver.java +++ b/app/src/main/java/com/github/axet/audiorecorder/services/BluetoothReceiver.java @@ -86,9 +86,8 @@ public class BluetoothReceiver extends BroadcastReceiver { String a = intent.getAction(); if (a == null) return; - if (bluetoothSource && a.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { + if (bluetoothSource && a.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) handler.postDelayed(connected, CONNECT_DELAY); - } if (bluetoothSource && a.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); switch (state) { diff --git a/app/src/main/java/com/github/axet/audiorecorder/services/ControlsService.java b/app/src/main/java/com/github/axet/audiorecorder/services/ControlsService.java index 2880a81..f7efdd7 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/services/ControlsService.java +++ b/app/src/main/java/com/github/axet/audiorecorder/services/ControlsService.java @@ -27,6 +27,7 @@ import com.github.axet.androidlibrary.services.PersistentService; import com.github.axet.androidlibrary.widgets.NotificationChannelCompat; import com.github.axet.androidlibrary.widgets.RemoteNotificationCompat; import com.github.axet.androidlibrary.widgets.RemoteViewsCompat; +import com.github.axet.audiolibrary.app.Sound; import com.github.axet.audiolibrary.app.Storage; import com.github.axet.audiorecorder.R; import com.github.axet.audiorecorder.activities.MainActivity; @@ -128,7 +129,7 @@ public class ControlsService extends PersistentService { title = getString(R.string.app_name); Uri f = storage.getStoragePath(); long free = Storage.getFree(context, f); - long sec = Storage.average(context, free); + long sec = Storage.average(context, Sound.getAudioFormat(context), free); text = AudioApplication.formatFree(context, free, sec); builder = new RemoteNotificationCompat.Low(context, R.layout.notifictaion); builder.setViewVisibility(R.id.notification_record, View.VISIBLE); diff --git a/app/src/main/java/com/github/axet/audiorecorder/widgets/RecordingSourcePreferenceCompat.java b/app/src/main/java/com/github/axet/audiorecorder/widgets/RecordingSourcePreferenceCompat.java new file mode 100644 index 0000000..60c571c --- /dev/null +++ b/app/src/main/java/com/github/axet/audiorecorder/widgets/RecordingSourcePreferenceCompat.java @@ -0,0 +1,79 @@ +package com.github.axet.audiorecorder.widgets; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.os.Build; +import android.preference.PreferenceManager; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.ListPreferenceDialogFragmentCompat; +import android.support.v7.preference.PreferenceViewHolder; +import android.util.AttributeSet; + +import com.github.axet.audiolibrary.app.Sound; +import com.github.axet.audiorecorder.R; +import com.github.axet.audiorecorder.app.AudioApplication; +import com.github.axet.audiorecorder.app.Storage; + +import java.util.ArrayList; +import java.util.Date; + +public class RecordingSourcePreferenceCompat extends ListPreference { + public RecordingSourcePreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public RecordingSourcePreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public RecordingSourcePreferenceCompat(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RecordingSourcePreferenceCompat(Context context) { + super(context); + } + + @Override + public boolean callChangeListener(Object newValue) { + update(newValue); + return super.callChangeListener(newValue); + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + Object def = super.onGetDefaultValue(a, index); + update(def); + return def; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + super.onSetInitialValue(restoreValue, defaultValue); + CharSequence[] text = getEntries(); + CharSequence[] values = getEntryValues(); + ArrayList tt = new ArrayList<>(); + ArrayList vv = new ArrayList<>(); + String raw = getContext().getString(R.string.source_raw); + String internal = getContext().getString(R.string.source_internal); + for (int i = 0; i < values.length; i++) { + String v = values[i].toString(); + String t = text[i].toString(); + if (v.equals(raw) && !Sound.isUnprocessedSupported(getContext())) + continue; + if (v.equals(internal) && Build.VERSION.SDK_INT < 29) + continue; + vv.add(v); + tt.add(t); + } + setEntryValues(vv.toArray(new CharSequence[0])); + setEntries(tt.toArray(new CharSequence[0])); + update(getValue()); // defaultValue null after defaults set + } + + public void update(Object value) { + String v = (String) value; + setSummary(v); + } +} diff --git a/app/src/main/res/raw-pl/about.html b/app/src/main/res/raw-pl/about.html index acd95e2..52ec077 100644 --- a/app/src/main/res/raw-pl/about.html +++ b/app/src/main/res/raw-pl/about.html @@ -12,7 +12,7 @@ Przyjazny dla systemu Android!

-

Audio Recorder with custom recording folder, nice recording volume indicator, recording notification, recording lock screen activity.

+

Rejestrator dźwięku z własnym folderem nagrywania, ładnym wskaźnikiem głośności nagrywania, powiadomieniem o nagrywaniu oraz sterowaniem nagrywania z poziomu blokady ekranu.

Licencja:
diff --git a/app/src/main/res/raw-pt-rBR/about.html b/app/src/main/res/raw-pt-rBR/about.html new file mode 100644 index 0000000..77f223b --- /dev/null +++ b/app/src/main/res/raw-pt-rBR/about.html @@ -0,0 +1,23 @@ + + + + + + +

Sobre

+

+ Compatível com Android! +

+ +

Gravador de áudio com pasta de gravação personalizada, controle na tela de bloqueio, indicador de volume e notificação de gravação.

+ +
+
Licença:
+
GPLv3
+
Código fonte:
+
https://gitlab.com/axet/android-audio-recorder
+
+ + diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index e6aff55..2b598a0 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -1,5 +1,11 @@ + + Mikrofon + Unprocessed + Bluetooth + Internal Audio + Audio Optager Auto luk om (%1$d) Optagelseslisten er tom\n\nKlik Optag for at starte optagelse diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 741d234..6a38a48 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -15,6 +15,7 @@ Mikrofon Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index e0c0786..5044801 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -13,6 +13,7 @@ Μικρόφωνο Unprocessed Bluetooth + Internal Audio Φωτεινό diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f608f07..11ab498 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -15,6 +15,7 @@ Mic Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 5b4600a..adce86c 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -15,6 +15,7 @@ Mikrofonoa Prozesatu gabea Bluetooth + Internal Audio diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 362a604..85d62e4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -15,6 +15,7 @@ Mic Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 8fa4e50..a0aeb3e 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -15,6 +15,7 @@ Mik Tidak diproses Bluetooth + Internal Audio diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 75cc319..21dd6fb 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -15,6 +15,7 @@ Mic Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1a19220..0818aff 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -15,6 +15,7 @@ Mic Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c6899c4..e09d887 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -13,8 +13,9 @@ Mikrofon - Unprocessed + Nieprzetworzone Bluetooth + Internal Audio @@ -27,52 +28,52 @@ Stereo - No folder view application installed + Brak zainstalowanej aplikacji do przeglądania folderów pauza (wstrzymane przez połączenie) nagrywanie - enkodowanie + kodowanie pauza edytuj Potwierdź anulowanie - Enkodowanie... + Kodowanie... Pauza... Nagrywanie - Otwórz Folder Nagrywania - Lista nagrań jest pusta\n\nKliknij Nagraj, aby rozpocząć nagrywanie + Otwórz folder z nagraniami + Lista nagrań jest pusta\n\nDotknij ikonki "mikrofonu", aby rozpocząć nagrywanie Nagrywaj Wytnij - Stop + Zatrzymaj Anuluj Pauza - Ścieżka Przechowywania + Folder nagrań Tempo Próbkowania - Enkodowanie + Kodowanie Wyjściowy format pliku (.wav, .m4a, ...) - Tryb - Recording channels - Format Nazwy + Kanały audio + Kanały nagrywania + Format pliku Wstrzymaj podczas połączeń - Zatrzymaj nagrywanie po odebraniu i kontynuuj podcas rozłączania - Tryb Wyciszenia - Przełącz telefon w \'tryb ciszy\' podczas nagrywania + Zatrzymaj nagrywanie po odebraniu i kontynuuj po rozłączeniu + Tryb cichy + Załącz \'tryb cichy\' podczas nagrywania Sterowanie z ekranu blokady Pokaż elementy sterujące, gdy telefon jest zablokowany Motyw Aplikacji - Ustaw motyw aplikacji (ciemny / jasny) + Ustaw motyw aplikacji (ciemny/jasny) Aplikacja Nagrania - Enkodowanie w Locie - Włączając enkodowanie w locie, wyłącza edytowanie i odzyskiwanie po awarii + Kodowanie "w locie" + Włączając kodowanie "w locie", wyłącza edytowanie i odzyskiwanie po awarii pauza (bluetooth rozłaczony) Szukaj Zapisz jako WAV - Auto close in (%1$d) - Mic muted - Android Pie and above prevent idle background apps from using microphone. Please disable selinux or install previous android version! - Mic paused by OS, recording time is less then data recorded, check if you device supports background recording or it is fast enougth for selected settings - Start Recording - Stop Recording - Background encoding paused due to android Battery Optimization settings, please allow this application work in background + Zamknij automatycznie za (%1$d) + Mikrofon wyciszony + Android 9 (Pie) i nowsze wersje uniemożliwiają bezczynnym aplikacjom działającym w tle korzystanie z mikrofonu. Prosimy o wyłączenie SeLinux lub aktualizację do wcześniejszej wersji Androida! + Mikrofon został wstrzymany przez system Android, czas nagrywania jest krótszy niż zapisane dane, sprawdź czy urządzenie obsługuje nagrywanie w tle lub czy jest wystarczająco szybkie dla wybranych ustawień + Rozpocznij nagrywanie + Zakończ nagrywanie + Kodowanie w tle zostało wstrzymane przez system Android w celu oszczędzania energii, proszę pozwolić tej aplikacji pracować w tle (ustawienia systemu: optymalizacja baterii) /s diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 2e3d367..cb1b487 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1,5 +1,5 @@ - Audio Recorder + Gravador de áudio 48 kHz @@ -8,18 +8,19 @@ 22 kHz 16 kHz (padrão) 11 kHz - 8 kHz (ligação de tel.) + 8 kHz (tipo ligação) Mic Não processado Bluetooth + Internal Audio - Tema Claro - Tema Escuro + Tema claro + Tema escuro @@ -27,52 +28,52 @@ Estéreo - Não foi encontrado nenhum aplicativo para explorar os arquivos - pausado (chamada atendida) + Não foi encontrado nenhum app para abrir os arquivos + pausado (ligação atendida) gravando codificando pausado editando - Deseja cancelar + Quer cancelar Codificando... Pausado... Gravando - Abrir pasta das gravações - A lista das gravações está vazia\n\nToque no ícone do microfone para começar a gravar + Abrir pasta de gravações + A lista de gravações está vazia\n\nToque no ícone do microfone para começar a gravar Gravar Cortar Parar Cancelar Pausar - Pasta das gravações + Pasta de gravações Taxa de amostragem Codificação - Formato de saída do arquivo (.wav, .mp3, etc.) + Tipo de arquivo de áudio (.wav, .mp3, etc.) Canais de áudio Canais de gravação - Formato do nome de arquivo - Pausar durante a chamada - e voltar a gravar quando a chamada for desligada + Formato de nome de arquivo + Pausar durante a ligação + e voltar a gravar quando a ligação for concluída Modo silencioso Ativar o \'modo silencioso\' durante a gravação - Controle da tela bloqueada - Mostrar os controles quando a tela estiver bloqueada + Controle na tela de bloqueio + Mostrar menu de controle quando a tela for bloqueada Tema do App Definir o tema (claro ou escuro) Aplicativo Gravações Codificação em tempo real - Ativando codificação em tempo real desabilitará a edição e recuperação após a falha + Ao permitir codificação em tempo real você desabilitará a edição e recuperação após uma falha pausado (bluetooth desconectado) Pesquisar - Salvar como WAV - Auto-fechar em (%1$d) + Salvar como .wav + Fechar autom. em (%1$d) Mic silenciado - Android 9 (Pie) e mais recente impedem que os Apps em segundo plano utilizem o microfone. Solução: ou desabilitar o SeLinux ou usar a versão anterior do Android! - Microfone foi pausado pelo Android, o tempo de gravação é menor do que o conteúdo gravado. Verifique se seu dispositivo suporta gravação em segundo plano ou se é o suficiente rápido para utilizar as configurações selecionadas - Iniciar Gravação - Parar a Gravação - Codificação em segundo plano foi pausada devido a configuração do Android de otimização da bateria, por favor permita que o App funcione em segundo plano + Android 9 (Pie) e mais recentes impedem que os apps usem o microfone em segundo plano. Solução: desabilite o SeLinux ou use uma versão mais antiga do Android + O microfone foi pausado pelo Android, o tempo de gravação é menor do que o conteúdo gravado. Verifique se seu dispositivo suporta gravação em segundo plano ou se é o suficientemente rápido para usar as configurações selecionadas + Iniciar uma gravação + Parar a gravação + A codificação em segundo plano foi pausada pela configuração de otimização da bateria do Android, por favor permita que o App funcione em segundo plano /s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 437e954..cf590ef 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -20,6 +20,7 @@ Микрофон Необработанный Bluetooth + Internal Audio diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 1de6978..8982d5d 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -15,6 +15,7 @@ Mikrofón Bez spracovania (surové) Bluetooth + Internal Audio diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 11a0e36..bd58eb2 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -15,6 +15,7 @@ Mikrofon İşlenmemiş Bluetooth + Internal Audio diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 0c946de..156469e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -15,6 +15,7 @@ 话筒 未处理 蓝牙 + Internal Audio diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 16deea3..e7bb31a 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -15,6 +15,7 @@ 麥克風 未處理 藍牙 + Internal Audio diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 003ca07..570c35f 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -7,6 +7,7 @@ default raw bluetooth + internal 48000 @@ -22,6 +23,17 @@ @string/source_mic @string/source_raw @string/source_bluetooth + @string/source_internal + + + + 16-bit PCM + 24-bit PCM (float) + + + + 16 + float diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 73d78fd..f52d4bd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ Mic Unprocessed Bluetooth + Internal Audio diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 7cf8dc3..f1c7715 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -8,6 +8,16 @@ android:title="@string/pref_storage_title" /> + + -