From fe90c9d9546e3663e31486bf2b78903f03055692 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Mon, 2 Nov 2020 12:01:40 +0300 Subject: [PATCH] add background encoding support --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 1 + .../activities/MainActivity.java | 156 ++++++- .../activities/RecordingActivity.java | 51 +-- .../audiorecorder/app/AudioApplication.java | 2 +- .../axet/audiorecorder/app/Recordings.java | 18 + .../services/EncodingService.java | 427 ++++++++++++++++++ .../services/OnBootReceiver.java | 1 + .../services/RecordingService.java | 26 +- build.gradle | 2 +- 10 files changed, 628 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/com/github/axet/audiorecorder/services/EncodingService.java diff --git a/app/build.gradle b/app/build.gradle index 9cc1537..84df5c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,7 +53,7 @@ android { dependencies { testImplementation 'junit:junit:4.12' - implementation 'com.github.axet:android-audio-library:1.0.175' // implementation project(':android-audio-library') + implementation 'com.github.axet:android-audio-library:1.0.176' // implementation project(':android-audio-library') implementation ('com.github.axet:wget:1.6.1') { 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 96282d4..8bb58f8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,7 @@ android:supportsRtl="true" android:theme="@style/RecThemeLight"> + 0) { + builder.setNeutralButton(R.string.save_as_wav, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + final OpenFileDialog d = new OpenFileDialog(context, OpenFileDialog.DIALOG_TYPE.FOLDER_DIALOG); + d.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + EncodingService.saveAsWAV(context, in, storage.getNewFile(d.getCurrentPath(), FormatWAV.EXT), info); + } + }); + d.show(); + } + }); + } + builder.show(); + } + + public void hide() { + snackbar.dismiss(); + } + } + @Override public int getAppTheme() { return AudioApplication.getTheme(this, R.style.RecThemeLight_NoActionBar, R.style.RecThemeDark_NoActionBar); @@ -72,6 +217,7 @@ public class MainActivity extends AppCompatThemeActivity { getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); setContentView(R.layout.activity_main); + final View content = findViewById(android.R.id.content); storage = new Storage(this); @@ -121,8 +267,11 @@ public class MainActivity extends AppCompatThemeActivity { } }; receiver.registerReceiver(this); + encoding = new EncodingDialog(); + encoding.registerReceiver(this); RecordingService.startIfPending(this); + EncodingService.startIfPending(this); try { new Recordings.ExoLoader(this, false); @@ -307,6 +456,7 @@ public class MainActivity extends AppCompatThemeActivity { super.onDestroy(); recordings.close(); receiver.close(); + encoding.close(); } void updateHeader() { 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 b2f88a4..316febc 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 @@ -2,7 +2,6 @@ package com.github.axet.audiorecorder.activities; import android.Manifest; import android.app.Activity; -import android.app.ProgressDialog; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; @@ -48,18 +47,14 @@ import com.github.axet.androidlibrary.widgets.Toast; import com.github.axet.audiolibrary.app.RawSamples; import com.github.axet.audiolibrary.app.Sound; import com.github.axet.audiolibrary.encoders.Factory; -import com.github.axet.audiolibrary.encoders.FileEncoder; import com.github.axet.audiolibrary.encoders.FormatWAV; -import com.github.axet.audiolibrary.encoders.OnFlyEncoding; -import com.github.axet.audiolibrary.filters.AmplifierFilter; -import com.github.axet.audiolibrary.filters.SkipSilenceFilter; -import com.github.axet.audiolibrary.filters.VoiceFilter; import com.github.axet.audiolibrary.widgets.PitchView; import com.github.axet.audiorecorder.BuildConfig; import com.github.axet.audiorecorder.R; import com.github.axet.audiorecorder.app.AudioApplication; import com.github.axet.audiorecorder.app.Storage; import com.github.axet.audiorecorder.services.BluetoothReceiver; +import com.github.axet.audiorecorder.services.EncodingService; import com.github.axet.audiorecorder.services.RecordingService; import com.github.axet.wget.SpeedInfo; @@ -84,7 +79,6 @@ public class RecordingActivity extends AppCompatThemeActivity { public static final String STOP_RECORDING = RecordingService.class.getCanonicalName() + ".STOP_RECORDING"; PhoneStateChangeListener pscl = new PhoneStateChangeListener(); - FileEncoder encoder; Headset headset; Intent recordSoundIntent = null; @@ -149,7 +143,7 @@ public class RecordingActivity extends AppCompatThemeActivity { } } if (msg.what == AudioApplication.RecordingStorage.ERROR) - Error((Exception) msg.obj); + Error((Throwable) msg.obj); } }; @@ -435,15 +429,7 @@ public class RecordingActivity extends AppCompatThemeActivity { } public String toMessage(Throwable e) { - Throwable t; - if (encoder == null) { - t = e; - } else { - t = encoder.getException(); - if (t == null) - t = e; - } - return ErrorDialog.toMessage(t); + return ErrorDialog.toMessage(e); } public void Error(Throwable e) { @@ -474,14 +460,7 @@ public class RecordingActivity extends AppCompatThemeActivity { d.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - OnFlyEncoding fly = new OnFlyEncoding(recording.storage, recording.storage.getNewFile(d.getCurrentPath(), FormatWAV.EXT), recording.getInfo()); - FileEncoder encoder = new FileEncoder(RecordingActivity.this, in, fly); - encoding(encoder, fly, new Runnable() { - @Override - public void run() { - finish(); - } - }); + EncodingService.saveAsWAV(RecordingActivity.this, recording.storage.getTempRecording(), recording.storage.getNewFile(d.getCurrentPath(), FormatWAV.EXT), recording.getInfo()); } }); d.show(); @@ -569,8 +548,6 @@ public class RecordingActivity extends AppCompatThemeActivity { done.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (encoder != null) - return; String msg; if (shared.getBoolean(AudioApplication.PREFERENCE_FLY, false)) msg = getString(R.string.recording_status_recording); @@ -749,7 +726,7 @@ public class RecordingActivity extends AppCompatThemeActivity { boolean r = recording.thread != null; - RecordingService.startService(this, Storage.getName(this, recording.targetUri), r, encoder != null, duration); + RecordingService.startService(this, Storage.getName(this, recording.targetUri), r, duration); if (r) { pitch.record(); @@ -780,7 +757,7 @@ public class RecordingActivity extends AppCompatThemeActivity { stopRecording(); - RecordingService.startService(this, Storage.getName(this, recording.targetUri), false, encoder != null, duration); + RecordingService.startService(this, Storage.getName(this, recording.targetUri), false, duration); final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); @@ -1038,11 +1015,6 @@ public class RecordingActivity extends AppCompatThemeActivity { play = null; } - if (encoder != null) { - encoder.close(); - encoder = null; - } - final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = shared.edit(); editor.remove(AudioApplication.PREFERENCE_TARGET); @@ -1065,7 +1037,7 @@ public class RecordingActivity extends AppCompatThemeActivity { recording.startRecording(); - RecordingService.startService(this, Storage.getName(this, recording.targetUri), true, encoder != null, duration); + RecordingService.startService(this, Storage.getName(this, recording.targetUri), true, duration); } catch (RuntimeException e) { Toast.Error(RecordingActivity.this, e); finish(); @@ -1076,7 +1048,7 @@ public class RecordingActivity extends AppCompatThemeActivity { long ms = samplesTime / recording.sampleRate * 1000; duration = AudioApplication.formatDuration(this, ms); time.setText(duration); - RecordingService.startService(this, Storage.getName(this, recording.targetUri), recording.thread != null, encoder != null, duration); + RecordingService.startService(this, Storage.getName(this, recording.targetUri), recording.thread != null, duration); } @Override @@ -1108,8 +1080,6 @@ public class RecordingActivity extends AppCompatThemeActivity { } } - final File in = recording.storage.getTempRecording(); - final Runnable last = new Runnable() { @Override public void run() { @@ -1120,12 +1090,14 @@ public class RecordingActivity extends AppCompatThemeActivity { } }; + final File in = recording.storage.getTempRecording(); + if (!in.exists() || in.length() == 0) { last.run(); return; } - final OnFlyEncoding fly = new OnFlyEncoding(recording.storage, recording.targetUri, recording.getInfo()); + EncodingService.startEncoding(this, in, recording.targetUri, recording.getInfo()); encoder = new FileEncoder(this, in, fly); @@ -1168,6 +1140,7 @@ public class RecordingActivity extends AppCompatThemeActivity { Error(encoder.getException()); } }); + last.run(); } @Override diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/AudioApplication.java b/app/src/main/java/com/github/axet/audiorecorder/app/AudioApplication.java index c2fc88c..da864c4 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/AudioApplication.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/AudioApplication.java @@ -344,7 +344,7 @@ public class AudioApplication extends com.github.axet.audiolibrary.app.MainAppli } } - public void Post(Exception e) { + public void Post(Throwable e) { Post(ERROR, e); } diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/Recordings.java b/app/src/main/java/com/github/axet/audiorecorder/app/Recordings.java index a4b54c4..8e44db0 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/Recordings.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/Recordings.java @@ -9,6 +9,11 @@ import android.widget.TextView; import com.github.axet.androidlibrary.widgets.ErrorDialog; import com.github.axet.audiorecorder.R; +import com.github.axet.audiorecorder.services.EncodingService; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; public class Recordings extends com.github.axet.audiolibrary.app.Recordings { public View progressEmpty; @@ -53,4 +58,17 @@ public class Recordings extends com.github.axet.audiolibrary.app.Recordings { done.run(); } } + + @Override + public void scan(List nn, boolean clean, Runnable done) { + EncodingService.EncodingStorage storage = new EncodingService.EncodingStorage(new Storage(context)); + for (Storage.Node n : new ArrayList<>(nn)) { + for (File key : storage.keySet()) { + EncodingService.EncodingStorage.Info info = storage.get(key); + if (n.uri.equals(info.targetUri)) + nn.remove(n); + } + } + super.scan(nn, clean, done); + } } diff --git a/app/src/main/java/com/github/axet/audiorecorder/services/EncodingService.java b/app/src/main/java/com/github/axet/audiorecorder/services/EncodingService.java new file mode 100644 index 0000000..a7a5022 --- /dev/null +++ b/app/src/main/java/com/github/axet/audiorecorder/services/EncodingService.java @@ -0,0 +1,427 @@ +package com.github.axet.audiorecorder.services; + +import android.annotation.SuppressLint; +import android.app.Notification; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.support.annotation.Nullable; +import android.util.Log; +import android.view.View; + +import com.github.axet.androidlibrary.app.AlarmManager; +import com.github.axet.androidlibrary.app.ProximityShader; +import com.github.axet.androidlibrary.preferences.OptimizationPreferenceCompat; +import com.github.axet.androidlibrary.services.PersistentService; +import com.github.axet.androidlibrary.widgets.RemoteNotificationCompat; +import com.github.axet.audiolibrary.app.RawSamples; +import com.github.axet.audiolibrary.app.Storage; +import com.github.axet.audiolibrary.encoders.FileEncoder; +import com.github.axet.audiolibrary.encoders.OnFlyEncoding; +import com.github.axet.audiolibrary.filters.AmplifierFilter; +import com.github.axet.audiolibrary.filters.SkipSilenceFilter; +import com.github.axet.audiolibrary.filters.VoiceFilter; +import com.github.axet.audiorecorder.R; +import com.github.axet.audiorecorder.activities.MainActivity; +import com.github.axet.audiorecorder.activities.RecordingActivity; +import com.github.axet.audiorecorder.app.AudioApplication; + +import org.apache.commons.io.FileUtils; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.FilenameFilter; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; + +public class EncodingService extends PersistentService { + public static final String TAG = EncodingService.class.getSimpleName(); + + public static final int NOTIFICATION_RECORDING_ICON = 2; + + public static String SHOW_ACTIVITY = EncodingService.class.getCanonicalName() + ".SHOW_ACTIVITY"; + public static String SAVE_AS_WAV = EncodingService.class.getCanonicalName() + ".SAVE_AS_WAV"; + public static String UPDATE_ENCODING = EncodingService.class.getCanonicalName() + ".UPDATE_ENCODING"; + public static String START_ENCODING = EncodingService.class.getCanonicalName() + ".START_ENCODING"; + public static String ERROR = EncodingService.class.getCanonicalName() + ".ERROR"; + + public static String JSON_EXT = "json"; + + static { + OptimizationPreferenceCompat.REFRESH = AlarmManager.MIN1; + } + + Storage storage; // for storage path + EncodingStorage encodings; + FileEncoder encoder; + + public static void startIfPending(Context context) { // if encoding pending + Storage storage = new Storage(context); + EncodingStorage enc = new EncodingStorage(storage); + if (!enc.isEmpty()) { + start(context); + return; + } + } + + public static void start(Context context) { // start persistent icon service + start(context, new Intent(context, EncodingService.class)); + } + + public static void saveAsWAV(Context context, File in, File out, RawSamples.Info info) { // start encoding process for selected file + String j; + try { + j = info.save().toString(); + } catch (JSONException e) { + throw new RuntimeException(e); + } + start(context, new Intent(context, EncodingService.class).setAction(SAVE_AS_WAV) + .putExtra("in", in) + .putExtra("out", out) + .putExtra("info", j) + ); + } + + public static void stop(Context context) { + stop(context, new Intent(context, EncodingService.class)); + } + + public void Error(File in, RawSamples.Info info, Throwable e) { + String json; + try { + json = info.save().toString(); + } catch (JSONException e1) { + throw new RuntimeException(e1); + } + sendBroadcast(new Intent(ERROR) + .putExtra("in", in) + .putExtra("info", json) + .putExtra("e", e) + ); + } + + public static void startEncoding(Context context, File in, Uri targetUri, RawSamples.Info info) { + EncodingStorage storage = new EncodingStorage(new Storage(context)); + storage.save(in, targetUri, info); + String json; + try { + json = info.save().toString(); + } catch (JSONException e) { + throw new RuntimeException(e); + } + start(context, new Intent(context, EncodingService.class).setAction(START_ENCODING) + .putExtra("in", in) + .putExtra("targetUri", targetUri) + .putExtra("info", json) + ); + } + + public static class EncodingStorage extends HashMap { + public Storage storage; + + public static File jsonFile(File f) { + return new File(f.getParentFile(), Storage.getNameNoExt(f) + "." + JSON_EXT); + } + + public static class Info { + public Uri targetUri; + public RawSamples.Info info; + + public Info() { + } + + public Info(Uri t, RawSamples.Info i) { + this.targetUri = t; + this.info = i; + } + + public Info(String json) throws JSONException { + load(new JSONObject(json)); + } + + public Info(JSONObject json) throws JSONException { + load(json); + } + + public JSONObject save() throws JSONException { + JSONObject json = new JSONObject(); + json.put("targetUri", targetUri.toString()); + json.put("info", info.save()); + return json; + } + + public void load(JSONObject json) throws JSONException { + targetUri = Uri.parse(json.getString("targetUri")); + info = new RawSamples.Info(json.getJSONObject("info")); + } + } + + public EncodingStorage(Storage s) { + storage = s; + load(); + } + + public void load() { + clear(); + File storage = this.storage.getTempRecording().getParentFile(); + File[] ff = storage.listFiles(new FilenameFilter() { + String start = Storage.getNameNoExt(Storage.TMP_ENC); + String ext = Storage.getExt(Storage.TMP_ENC); + + @Override + public boolean accept(File dir, String name) { + return name.startsWith(start) && name.endsWith("." + ext); + } + }); + if (ff == null) + return; + for (File f : ff) { + File j = jsonFile(f); + try { + put(f, new Info(new JSONObject(FileUtils.readFileToString(j, Charset.defaultCharset())))); + } catch (Exception e) { + Log.d(TAG, "unable to read json", e); + } + } + } + + public void save(File in, Uri targetUri, RawSamples.Info info) { + File to = storage.getTempEncoding(); + to = Storage.getNextFile(to); + to = Storage.move(in, to); + try { + File j = jsonFile(to); + Info rec = new Info(targetUri, info); + JSONObject json = rec.save(); + FileUtils.writeStringToFile(j, json.toString(), Charset.defaultCharset()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public ArrayList asList() { + ArrayList list = new ArrayList<>(); + for (File key : keySet()) { + EncodingStorage.Info k = get(key); + list.add(k.targetUri.toString()); + } + return list; + } + } + + public EncodingService() { + } + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public void onCreateOptimization() { + storage = new Storage(this); + encodings = new EncodingStorage(storage); + optimization = new OptimizationPreferenceCompat.ServiceReceiver(this, NOTIFICATION_RECORDING_ICON, null, AudioApplication.PREFERENCE_NEXT) { + Intent notificationIntent; + + @Override + public void onCreateIcon(Service service, int id) { + icon = new OptimizationPreferenceCompat.OptimizationIcon(service, id, key) { + @Override + public void updateIcon() { + icon.updateIcon(new Intent()); + } + + @Override + public void updateIcon(Intent intent) { + super.updateIcon(intent); + notificationIntent = intent; + } + + @SuppressLint("RestrictedApi") + public Notification build(Intent intent) { + String targetFile = intent.getStringExtra("targetFile"); + int progress = intent.getIntExtra("progress", 0); + + PendingIntent main; + + RemoteNotificationCompat.Builder builder; + + String title; + String text; + + title = getString(R.string.encoding_title); + text = ".../" + targetFile + " (" + progress + "%)"; + builder = new RemoteNotificationCompat.Low(context, R.layout.notifictaion); + builder.setViewVisibility(R.id.notification_record, View.VISIBLE); + builder.setViewVisibility(R.id.notification_pause, View.GONE); + main = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + + builder.setViewVisibility(R.id.notification_pause, View.GONE); + builder.setViewVisibility(R.id.notification_record, View.GONE); + + builder.setTheme(AudioApplication.getTheme(context, R.style.RecThemeLight, R.style.RecThemeDark)) + .setChannel(AudioApplication.from(context).channelStatus) + .setImageViewTint(R.id.icon_circle, builder.getThemeColor(R.attr.colorButtonNormal)) + .setTitle(title) + .setText(text) + .setWhen(icon.notification) + .setMainIntent(main) + .setAdaptiveIcon(R.drawable.ic_launcher_foreground) + .setSmallIcon(R.drawable.ic_launcher_notification) + .setOngoing(true); + + return builder.build(); + } + }; + icon.create(); + } + + @Override + public boolean isOptimization() { + return true; // we are not using optimization preference + } + }; + optimization.create(); + } + + @Override + public void onStartCommand(Intent intent) { + String a = intent.getAction(); + if (a == null) { + optimization.icon.updateIcon(intent); + } else if (a.equals(SHOW_ACTIVITY)) { + ProximityShader.closeSystemDialogs(this); + if (intent.getStringExtra("targetFile") == null) + MainActivity.startActivity(this); + else + RecordingActivity.startActivity(this, !intent.getBooleanExtra("recording", false)); + } else if (a.equals(SAVE_AS_WAV)) { + File in = (File) intent.getSerializableExtra("in"); + File out = (File) intent.getSerializableExtra("out"); + RawSamples.Info info; + try { + info = new RawSamples.Info(intent.getStringExtra("info")); + } catch (JSONException e) { + throw new RuntimeException(e); + } + if (encoder == null) { + OnFlyEncoding fly = new OnFlyEncoding(storage, out, info); + encoder = new FileEncoder(this, in, fly); + encoding(encoder, fly, info, new Runnable() { + @Override + public void run() { + encoder.close(); + encoder = null; + startEncoding(); + } + }); + } + } else if (a.equals(START_ENCODING)) { + File in = (File) intent.getSerializableExtra("in"); + Uri targetUri = intent.getParcelableExtra("targetUri"); + RawSamples.Info info; + try { + info = new RawSamples.Info(intent.getStringExtra("info")); + } catch (JSONException e) { + throw new RuntimeException(e); + } + if (encoder == null) { + OnFlyEncoding fly = new OnFlyEncoding(storage, targetUri, info); + encoder = new FileEncoder(this, in, fly); + encoding(encoder, fly, info, new Runnable() { + @Override + public void run() { + encoder.close(); + encoder = null; + startEncoding(); + } + }); + } + } + startEncoding(); + } + + public void startEncoding() { + if (encoder != null) + return; + SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); + encodings.load(); + for (File in : encodings.keySet()) { + EncodingStorage.Info info = encodings.get(in); + final OnFlyEncoding fly = new OnFlyEncoding(this.storage, info.targetUri, info.info); + + encoder = new FileEncoder(this, in, fly); + + if (shared.getBoolean(AudioApplication.PREFERENCE_VOICE, false)) + encoder.filters.add(new VoiceFilter(info.info)); + float amp = shared.getFloat(AudioApplication.PREFERENCE_VOLUME, 1); + if (amp != 1) + encoder.filters.add(new AmplifierFilter(amp)); + if (shared.getBoolean(AudioApplication.PREFERENCE_SKIP, false)) + encoder.filters.add(new SkipSilenceFilter(info.info)); + + encoding(encoder, fly, info.info, new Runnable() { + @Override + public void run() { + encoder.close(); + encoder = null; + startEncoding(); + } + }); + + return; + } + stopSelf(); + } + + void encoding(final FileEncoder encoder, final OnFlyEncoding fly, final RawSamples.Info info, final Runnable done) { + encoder.run(new Runnable() { + @Override + public void run() { + Intent intent = new Intent(UPDATE_ENCODING) + .putExtra("progress", encoder.getProgress()) + .putExtra("targetUri", fly.targetUri) + .putExtra("targetFile", Storage.getName(EncodingService.this, fly.targetUri)); + sendBroadcast(intent); + optimization.icon.updateIcon(intent); + } + }, new Runnable() { + @Override + public void run() { // success + Storage.delete(encoder.in); // delete raw recording + Storage.delete(EncodingStorage.jsonFile(encoder.in)); // delete json file + sendBroadcast(new Intent(UPDATE_ENCODING) + .putExtra("progress", 100) + .putExtra("targetUri", fly.targetUri) + ); + done.run(); + } + }, new Runnable() { + @Override + public void run() { // or error + Storage.delete(EncodingService.this, fly.targetUri); // fly has fd, delete target manually + Error(encoder.in, info, encoder.getException()); + stopSelf(); + } + }); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onDestroy() { + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/github/axet/audiorecorder/services/OnBootReceiver.java b/app/src/main/java/com/github/axet/audiorecorder/services/OnBootReceiver.java index c0496bd..e10fbd7 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/services/OnBootReceiver.java +++ b/app/src/main/java/com/github/axet/audiorecorder/services/OnBootReceiver.java @@ -12,5 +12,6 @@ public class OnBootReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent i) { Log.d(TAG, "onReceive"); RecordingService.startIfPending(context); + EncodingService.startIfPending(context); } } diff --git a/app/src/main/java/com/github/axet/audiorecorder/services/RecordingService.java b/app/src/main/java/com/github/axet/audiorecorder/services/RecordingService.java index e3f859a..3073fe9 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/services/RecordingService.java +++ b/app/src/main/java/com/github/axet/audiorecorder/services/RecordingService.java @@ -19,8 +19,8 @@ import android.widget.RemoteViews; import com.github.axet.androidlibrary.app.AlarmManager; import com.github.axet.androidlibrary.app.ProximityShader; -import com.github.axet.androidlibrary.services.PersistentService; import com.github.axet.androidlibrary.preferences.OptimizationPreferenceCompat; +import com.github.axet.androidlibrary.services.PersistentService; import com.github.axet.androidlibrary.widgets.RemoteNotificationCompat; import com.github.axet.androidlibrary.widgets.RemoteViewsCompat; import com.github.axet.audiolibrary.app.Storage; @@ -32,7 +32,8 @@ import com.github.axet.audiorecorder.app.AudioApplication; import java.io.File; /** - * Sometimes RecordingActivity started twice when launched from lockscreen. We need service and move recording into Application object. + * Sometimes RecordingActivity started twice when launched from lockscreen. + * We need service and keep recording into Application object. */ public class RecordingService extends PersistentService { public static final String TAG = RecordingService.class.getSimpleName(); @@ -49,16 +50,16 @@ public class RecordingService extends PersistentService { Storage storage; // for storage path - public static void startIfEnabled(Context context) { + public static void startIfEnabled(Context context) { // notification controls enabled? SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); if (!shared.getBoolean(AudioApplication.PREFERENCE_CONTROLS, false)) return; start(context); } - public static void startIfPending(Context context) { - Storage st = new Storage(context); - if (st.recordingPending()) { + public static void startIfPending(Context context) { // if recording pending or controls enabled + Storage storage = new Storage(context); + if (storage.recordingPending()) { final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); String f = shared.getString(AudioApplication.PREFERENCE_TARGET, ""); String d; @@ -73,21 +74,20 @@ public class RecordingService extends PersistentService { File file = new File(f); d = file.getName(); } - startService(context, d, false, false, null); + startService(context, d, false, null); return; } startIfEnabled(context); } - public static void start(Context context) { + public static void start(Context context) { // start persistent icon service start(context, new Intent(context, RecordingService.class)); } - public static void startService(Context context, String targetFile, boolean recording, boolean encoding, String duration) { + public static void startService(Context context, String targetFile, boolean recording, String duration) { // start recording / pause service start(context, new Intent(context, RecordingService.class) .putExtra("targetFile", targetFile) .putExtra("recording", recording) - .putExtra("encoding", encoding) .putExtra("duration", duration) ); } @@ -137,7 +137,7 @@ public class RecordingService extends PersistentService { public Notification build(Intent intent) { String targetFile = intent.getStringExtra("targetFile"); boolean recording = intent.getBooleanExtra("recording", false); - boolean encoding = intent.getBooleanExtra("encoding", false); + boolean encoding = false; String duration = intent.getStringExtra("duration"); PendingIntent main; @@ -146,7 +146,7 @@ public class RecordingService extends PersistentService { String title; String text; - if (targetFile == null) { + if (targetFile == null) { // buildPersistentIcon(); title = getString(R.string.app_name); Uri f = storage.getStoragePath(); long free = Storage.getFree(context, f); @@ -156,7 +156,7 @@ public class RecordingService extends PersistentService { builder.setViewVisibility(R.id.notification_record, View.VISIBLE); builder.setViewVisibility(R.id.notification_pause, View.GONE); main = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); - } else { + } else { // buildRecordingIcon(); if (recording) title = getString(R.string.recording_title); else diff --git a/build.gradle b/build.gradle index e60b369..f3e1ce6 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.github.axet:gradle-android-dx:0.0.4' } }