Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7fa15c7 authored by Joey's avatar Joey
Browse files

Recorder: friendship with storage ended, MediaProvider is my new best friend



Signed-off-by: default avatarJoey <joey@lineageos.org>
Change-Id: I73fb54386f7d26b9662f0c95a201b49ebfdc4944
parent 7f8a0979
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -19,11 +19,14 @@ import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -88,7 +91,7 @@ public class DialogActivity extends AppCompatActivity implements
            setupAsSettingsScreen();
        }

        animateAppareance();
        animateAppearance();

        boolean deleteLastRecording = intent.getBooleanExtra(EXTRA_DELETE_LAST_RECORDING, false);
        if (deleteLastRecording) {
@@ -126,7 +129,7 @@ public class DialogActivity extends AppCompatActivity implements
        }
    }

    private void animateAppareance() {
    private void animateAppearance() {
        mRootView.setAlpha(0f);
        mRootView.animate()
                .alpha(1f)
@@ -150,21 +153,24 @@ public class DialogActivity extends AppCompatActivity implements

    private void playLastItem(boolean isSound) {
        String type = isSound ? TYPE_AUDIO : TYPE_VIDEO;
        String path = LastRecordHelper.getLastItemPath(this, isSound);
        startActivityForResult(LastRecordHelper.getOpenIntent(this, path, type), 0);
        Uri uri = LastRecordHelper.getLastItemUri(this, isSound);
        Intent intent = LastRecordHelper.getOpenIntent(uri, type);
        if (intent != null) {
            startActivityForResult(intent, 0);
        }
    }

    private void deleteLastItem(boolean isSound) {
        String path = LastRecordHelper.getLastItemPath(this, isSound);
        AlertDialog dialog = LastRecordHelper.deleteFile(this, path, isSound);
        Uri uri = LastRecordHelper.getLastItemUri(this, isSound);
        AlertDialog dialog = LastRecordHelper.deleteFile(this, uri, isSound);
        dialog.setOnDismissListener(d -> finish());
        dialog.show();
    }

    private void shareLastItem(boolean isSound) {
        String type = isSound ? TYPE_AUDIO : TYPE_VIDEO;
        String path = LastRecordHelper.getLastItemPath(this, isSound);
        startActivity(LastRecordHelper.getShareIntent(this, path, type));
        Uri uri = LastRecordHelper.getLastItemUri(this, isSound);
        startActivity(LastRecordHelper.getShareIntent(uri, type));
    }

    private void setupAsSettingsScreen() {
+6 −3
Original line number Diff line number Diff line
@@ -253,7 +253,6 @@ public class RecorderActivity extends AppCompatActivity implements
        if (mSoundService.isRecording()) {
            // Stop
            mSoundService.stopRecording();
            mSoundService.createShareNotification();
            stopService(new Intent(this, SoundRecorderService.class));
            Utils.setStatus(this, Utils.UiStatus.NOTHING);
        } else {
@@ -279,6 +278,10 @@ public class RecorderActivity extends AppCompatActivity implements
            // Start
            MediaProjectionManager mediaProjectionManager = getSystemService(
                    MediaProjectionManager.class);
            if (mediaProjectionManager == null) {
                return;
            }

            Intent permissionIntent = mediaProjectionManager.createScreenCaptureIntent();
            startActivityForResult(permissionIntent, REQUEST_AUDIO_VIDEO);
        }
@@ -432,8 +435,8 @@ public class RecorderActivity extends AppCompatActivity implements
    }

    private void updateLastItemStatus() {
        String lastScreen = LastRecordHelper.getLastItemPath(this, false);
        String lastSound = LastRecordHelper.getLastItemPath(this, true);
        Uri lastScreen = LastRecordHelper.getLastItemUri(this, false);
        Uri lastSound = LastRecordHelper.getLastItemUri(this, true);

        if (lastScreen == null) {
            mScreenLast.setVisibility(View.GONE);
+19 −11
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.os.StatFs;
@@ -40,10 +41,12 @@ import android.util.Log;
import android.view.Surface;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

import org.lineageos.recorder.R;
import org.lineageos.recorder.RecorderActivity;
import org.lineageos.recorder.utils.MediaProviderHelper;
import org.lineageos.recorder.utils.LastRecordHelper;
import org.lineageos.recorder.utils.Utils;

@@ -55,7 +58,7 @@ import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

public class ScreencastService extends Service {
public class ScreencastService extends Service implements MediaProviderHelper.OnContentWritten {
    private static final String LOGTAG = "ScreencastService";

    private static final String SCREENCAST_NOTIFICATION_CHANNEL =
@@ -190,6 +193,14 @@ public class ScreencastService extends Service {
        super.onDestroy();
    }

    @Override
    public void onContentWritten(@Nullable String uri) {
        stopForeground(true);
        if (uri != null) {
            sendShareNotification(uri);
        }
    }

    private int startScreencasting(Intent intent) {
        if (hasNoAvailableSpace()) {
            Toast.makeText(this, R.string.screen_insufficient_storage,
@@ -299,10 +310,8 @@ public class ScreencastService extends Service {
            mTimer.cancel();
            mTimer = null;
        }
        stopForeground(true);
        if (mPath != null) {
            sendShareNotification(mPath.getPath());
        }

        MediaProviderHelper.addVideoToContentProvider(getContentResolver(), mPath, this);
    }

    private void stopCasting() {
@@ -334,24 +343,23 @@ public class ScreencastService extends Service {
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    }

    private NotificationCompat.Builder createShareNotificationBuilder(String file) {
    private NotificationCompat.Builder createShareNotificationBuilder(String uriStr) {
        Uri uri = Uri.parse(uriStr);
        Intent intent = new Intent(this, RecorderActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);

        PendingIntent playPIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getOpenIntent(this, file, "video/mp4"),
                LastRecordHelper.getOpenIntent(uri, "video/mp4"),
                PendingIntent.FLAG_CANCEL_CURRENT);
        PendingIntent sharePIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getShareIntent(this, file, "video/mp4"),
                LastRecordHelper.getShareIntent(uri, "video/mp4"),
                PendingIntent.FLAG_CANCEL_CURRENT);
        PendingIntent deletePIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getDeleteIntent(this, false),
                PendingIntent.FLAG_CANCEL_CURRENT);

        long timeElapsed = SystemClock.elapsedRealtime() - mStartTime;
        LastRecordHelper.setLastItem(this, file, timeElapsed, false);

        Log.i(LOGTAG, "Video complete: " + file);
        LastRecordHelper.setLastItem(this, uriStr, timeElapsed, false);

        return new NotificationCompat.Builder(this, SCREENCAST_NOTIFICATION_CHANNEL)
                .setWhen(System.currentTimeMillis())
+21 −8
Original line number Diff line number Diff line
@@ -27,9 +27,12 @@ import android.content.IntentFilter;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import android.text.format.DateUtils;
@@ -38,6 +41,7 @@ import android.util.Log;
import org.lineageos.recorder.R;
import org.lineageos.recorder.RecorderActivity;
import org.lineageos.recorder.utils.LastRecordHelper;
import org.lineageos.recorder.utils.MediaProviderHelper;
import org.lineageos.recorder.utils.Utils;

import java.io.BufferedOutputStream;
@@ -50,7 +54,7 @@ import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

public class SoundRecorderService extends Service {
public class SoundRecorderService extends Service implements MediaProviderHelper.OnContentWritten {

    static final String EXTENSION = ".pcm";
    private static final String ACTION_STARTED = "org.lineageos.recorder.sounds.STARTED_SOUND";
@@ -134,6 +138,17 @@ public class SoundRecorderService extends Service {
        super.onDestroy();
    }

    @Override
    public void onContentWritten(@Nullable String uri) {
        mStatus = RecorderStatus.STOPPED;
        mOutFilePath = uri;
        Intent intent = new Intent(ACTION_STOPPED);
        intent.putExtra(EXTRA_FILE, mOutFilePath);
        sendBroadcast(intent);
        createShareNotification();
        stopForeground(true);
    }

    public boolean isRecording() {
        return mStatus == RecorderStatus.RECORDING;
    }
@@ -201,11 +216,8 @@ public class SoundRecorderService extends Service {
            oldFile.delete();
        }

        mStatus = RecorderStatus.STOPPED;
        Intent intent = new Intent(ACTION_STOPPED);
        intent.putExtra(EXTRA_FILE, mOutFilePath);
        sendBroadcast(intent);
        stopForeground(true);
        MediaProviderHelper.addSoundToContentProvider(
                getContentResolver(), new File(mOutFilePath), this);
    }

    private File createNewAudioFile() {
@@ -307,14 +319,15 @@ public class SoundRecorderService extends Service {
    }

    public void createShareNotification() {
        Uri outFileUri = Uri.parse(mOutFilePath);
        Intent intent = new Intent(this, RecorderActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);

        PendingIntent playPIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getOpenIntent(this, mOutFilePath, "audio/wav"),
                LastRecordHelper.getOpenIntent(outFileUri, "audio/wav"),
                PendingIntent.FLAG_CANCEL_CURRENT);
        PendingIntent sharePIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getShareIntent(this, mOutFilePath, "audio/wav"),
                LastRecordHelper.getShareIntent(outFileUri, "audio/wav"),
                PendingIntent.FLAG_CANCEL_CURRENT);
        PendingIntent deletePIntent = PendingIntent.getActivity(this, 0,
                LastRecordHelper.getDeleteIntent(this, true),
+10 −31
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import androidx.core.content.FileProvider;

import androidx.appcompat.app.AlertDialog;

import org.lineageos.recorder.DialogActivity;
@@ -36,21 +36,16 @@ public class LastRecordHelper {
    private static final String KEY_LAST_SCREEN = "screen_last_path";
    private static final String KEY_LAST_SOUND_TIME = "sound_last_duration";
    private static final String KEY_LAST_SCREEN_TIME = "screen_last_duration";
    private static final String FILE_PROVIDER = "org.lineageos.recorder.fileprovider";

    private LastRecordHelper() {
    }

    public static AlertDialog deleteFile(Context context, final String path, boolean isSound) {
    public static AlertDialog deleteFile(Context context, final Uri uri, boolean isSound) {
        return new AlertDialog.Builder(context)
                .setTitle(R.string.delete_title)
                .setMessage(context.getString(R.string.delete_message, path))
                .setMessage(context.getString(R.string.delete_message, uri))
                .setPositiveButton(R.string.delete, (dialog, which) -> {
                    File record = new File(path);
                    if (record.exists()) {
                        //noinspection ResultOfMethodCallIgnored
                        record.delete();
                    }
                    MediaProviderHelper.remove(context.getContentResolver(), uri);
                    NotificationManager nm = context.getSystemService(NotificationManager.class);
                    if (nm == null) {
                        return;
@@ -67,20 +62,15 @@ public class LastRecordHelper {
                .create();
    }

    public static Intent getShareIntent(Context context, String filePath, String mimeType) {
        File file = new File(filePath);
        Uri uri = FileProvider.getUriForFile(context, FILE_PROVIDER, file);
    public static Intent getShareIntent(Uri uri, String mimeType) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType(mimeType);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.putExtra(Intent.EXTRA_SUBJECT, file.getName());
        intent.setDataAndType(uri, mimeType);
        Intent chooserIntent = Intent.createChooser(intent, null);
        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        return chooserIntent;
    }

    public static Intent getOpenIntent(Context context, String filePath, String mimeType) {
        Uri uri = FileProvider.getUriForFile(context, FILE_PROVIDER, new File(filePath));
    public static Intent getOpenIntent(Uri uri, String mimeType) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(uri, mimeType);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -106,9 +96,10 @@ public class LastRecordHelper {
                .apply();
    }

    public static String getLastItemPath(Context context, boolean isSound) {
    public static Uri getLastItemUri(Context context, boolean isSound) {
        SharedPreferences prefs = context.getSharedPreferences(PREFS, 0);
        return prefs.getString(isSound ? KEY_LAST_SOUND : KEY_LAST_SCREEN, null);
        String uriStr = prefs.getString(isSound ? KEY_LAST_SOUND : KEY_LAST_SCREEN, null);
        return uriStr == null ? null : Uri.parse(uriStr);
    }

    private static long getLastItemDuration(Context context, boolean isSound) {
@@ -116,20 +107,8 @@ public class LastRecordHelper {
        return prefs.getLong(isSound ? KEY_LAST_SOUND_TIME : KEY_LAST_SCREEN_TIME, -1);
    }

    private static String getLastItemDate(Context context, boolean isSound) {
        String path = getLastItemPath(context, isSound);
        String[] pathParts = path.split("/");
        String[] date = pathParts[pathParts.length - 1]
                .replace(isSound ? ".wav" : ".mp4", "")
                .replace(isSound ? "SoundRecord" : "ScreenRecord", "")
                .split("-");
        return context.getString(R.string.date_format, date[1], date[2], date[3],
                date[4], date[5]);
    }

    public static String getLastItemDescription(Context context, boolean isSound) {
        return context.getString(R.string.screen_last_message,
                getLastItemDate(context, isSound),
                getLastItemDuration(context, isSound) / 1000);
    }
}
Loading