MediaRecorder不会在android中录制双方的录音

问题描述 投票:0回答:2

我无法在android中录制双方的音频。使用以下代码仅录制一侧音频。 android可以录音吗?

公共类CallRecordingService扩展服务{

private MediaPlayer mPlayer = null;
private MediaRecorder mRecorder = null;
private static final String LOG_TAG = CallRecordingService.class.getSimpleName();
private String savingPath;
boolean isRecordStarted = false;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    savingPath = intent.getStringExtra("OUTPUT_PATH");
    AppApplication.getInstance().saveIntoPrefs(MConstants.RECORDING_FILE_PATH, savingPath);
    startRecording();
    return START_NOT_STICKY;
}

// this process must be done prior to the start of recording
private void resetRecorder() {
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mRecorder.setAudioEncodingBitRate(48000);
    } else {
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mRecorder.setAudioEncodingBitRate(64000);
    }
    mRecorder.setAudioSamplingRate(8000);
    mRecorder.setOutputFile(savingPath);

    try {
        mRecorder.prepare();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void startRecording() {
    if (mRecorder != null) {
        mRecorder.stop();
        mRecorder.release();
    }
    mRecorder = new MediaRecorder();
    resetRecorder();
    try {
        // Sometimes prepare takes some time to complete
        Thread.sleep(2000);
        if (!isRecordStarted) {
            mRecorder.start();
            isRecordStarted = true;
        } else if (isRecordStarted) {
            isRecordStarted = false;
            stopRecording();
        }
    } catch (InterruptedException | IllegalStateException e) {
        e.printStackTrace();
    }
}

public void stopRecording() {
    if (mRecorder != null) {
        mRecorder.stop();
        mRecorder.reset();
        mRecorder.release();
        mRecorder = null;
    }
}

}

我被迫在我的应用程序中实现此录制功能。如果有人完成了这种实现,那么请解决我的错误。

android mediarecorder
2个回答
0
投票

AndroidManifest.xml

<manifest>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    ....
    <application>
    ....
    <service
        android:name=".CallForegroundService"
        android:enabled="true"
        android:exported="false" />
    </application>
</manifest>

ForegroundService

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CallForegroundService extends Service {

    private static final String TAG = "ForegroundService";
    private boolean isStarted;
    private MediaRecorder mRecorder;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startRecording(number);
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopRecording();
    }

    private void startRecording(String number) {
        try {
            String path = getApplicationContext().getFilesDir().getPath();
            //String selectedPath = Environment.getExternalStorageDirectory() + "/Testing";
            //String selectedPath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/Android/data/" + packageName + "/system_sound";

            File file = new File(path);
            if (!file.exists()){
                file.mkdirs();
            }

            mRecorder = new MediaRecorder();
            mRecorder.reset();

            String manufacturer = Build.MANUFACTURER;
            Log.d(TAG, manufacturer);
            /*if (manufacturer.toLowerCase().contains("samsung")) {
                mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
            } else {
                mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
            }*/
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //MIC | VOICE_COMMUNICATION | VOICE_RECOGNITION |
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //THREE_GPP | MPEG_4
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //AMR_NB | AAC
            String mFilePath = file + "/" + "REC_" + number + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".3gp"; //.3gp | .mp3
            mRecorder.setOutputFile(mFilePath);
            mRecorder.prepare();
            mRecorder.start();
            isStarted = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void stopRecording() {
        if (isStarted && mRecorder != null) {
            mRecorder.stop();
            mRecorder.reset(); // You can reuse the object by going back to setAudioSource() step
            mRecorder.release();
            mRecorder = null;
            isStarted = false;
        }
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {
    ArrayList<String> mArrayList;
    MediaPlayer mPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(this);
    }

    private void startService(Context context) {
        ContextCompat.startForegroundService(context, new Intent(context, CallForegroundService.class)); //ForegroundService
    }

    private void stopService(Context context) {
        context.stopService(new Intent(context, CallForegroundService.class)); //ForegroundService
    }

    //RecyclerView.Adapter
    private void getInternalStorageFiles() {
        mArrayList = new ArrayList<>();
        String path = getApplicationContext().getFilesDir().getPath();
        String[] listOfFiles = getApplicationContext().getFilesDir().list();
        Log.d(TAG, "Files: " + new Gson().toJson(listOfFiles));
        if (listOfFiles != null) {
            for (String fileName : listOfFiles) {
                mArrayList.add(fileName+"/"+path));
            }
        }
    }
    private void playRecord(Record model) {
        mPlayer = new MediaPlayer();
        try {
            FileInputStream mInputStream = new FileInputStream(mArrayList.get(i)); //i = for loop
            mPlayer.setDataSource(mInputStream.getFD());
            mInputStream.close();
            mPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mPlayer.start();
    }
    private void stopRecord() {
        if (mPlayer != null) {
            mPlayer.stop();
        }
    }
}

0
投票

等级

implementation 'pub.devrel:easypermissions:3.0.0'

Manifest.xml

<manifest>

    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

    <!-- AccessibilityService -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application>

        <!-- Accessibility Service -->
        <service android:name=".services.CallAccessibilityService"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            android:label="@string/accessibility_service_label">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_service_config" />
        </service>
<application>

res> xml> accessibility_service_config

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:accessibilityFlags="flagDefault"
    android:canRequestEnhancedWebAccessibility="true"
    android:notificationTimeout="100"
    android:packageNames="@null"
    android:canRetrieveWindowContent="true"
    android:canRequestTouchExplorationMode="true"
    />

MainActivity

public class MainActivity extends AppCompatActivity implements CallRecordAdapter.CallBackListener, EasyPermissions.PermissionCallbacks {

    //Link: https://developer.android.com/guide/topics/media/mediarecorder?hl=en

    private String[] PERMISSIONS = {
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.MODIFY_AUDIO_SETTINGS
    };

    private static final int CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084;
    private static final int RC_APP_PERM = 124;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //-----------------------------------------------| List of Permissions
        requestPermissions();
    }

    @AfterPermissionGranted(RC_APP_PERM)
    private void requestPermissions() {
        if (EasyPermissions.hasPermissions(this, PERMISSIONS)) {
            // Already have permission, do the thing
            onCheckPermissionOverOtherApp();
        } else {
            // Do not have permissions, request them now
            EasyPermissions.requestPermissions(this, "This app needs access to your camera and mic to make video calls", RC_APP_PERM, PERMISSIONS);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        // Some permissions have been granted
        onCheckPermissionOverOtherApp();
        getInternalStorageFiles();
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        // Some permissions have been denied
    }

    //===============================================| On over other app | open the settings screen
    private void onCheckPermissionOverOtherApp() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_DRAW_OVER_OTHER_APP_PERMISSION);
        } else {
            if (!isAccessibilitySettingsOn(getApplicationContext())) {
                startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
            if (!isAccessibilitySettingsOn(getApplicationContext())) {
                startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
            }
        } else {
            onCheckPermissionOverOtherApp();
            Toast.makeText(this,"Draw over other app permission not available. Closing the application", Toast.LENGTH_SHORT).show();
        }
    }

// To check if service is enabled
    public boolean isAccessibilitySettingsOn(Context mContext) {
        int accessibilityEnabled = 0;
        final String service = mContext.getPackageName() + "/" + CallAccessibilityService.class.getCanonicalName();
        try {
            accessibilityEnabled = Settings.Secure.getInt(mContext.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
            Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
        } catch (Settings.SettingNotFoundException e) {
            Log.e(TAG, "Error finding setting, default accessibility to not found: " + e.getMessage());
        }
        TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');

        if (accessibilityEnabled == 1) {
            Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
            String settingValue = Settings.Secure.getString(mContext.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            if (settingValue != null) {
                mStringColonSplitter.setString(settingValue);
                while (mStringColonSplitter.hasNext()) {
                    String accessibilityService = mStringColonSplitter.next();
                    Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
                    if (accessibilityService.equalsIgnoreCase(service)) {
                        Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
                        return true;
                    }
                }
            }
        } else {
            Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
        }
        return false;
    }


}

CallAccessibilityService

public class CallAccessibilityService extends AccessibilityService {

    private static final String TAG = "MyAccessibilityService";
    private FrameLayout mLayout;
    private boolean isStarted;
    private MediaRecorder mRecorder;

    private View mView;
    private WindowManager mWindowManager;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {

    }

    @Override
    public void onInterrupt() {
    }

    @Override
    protected void onServiceConnected() {


        displayView();
    }

    private void displayView() {
        //Inflate the floating view layout we created
        mView = LayoutInflater.from(this).inflate(R.layout.action_bar, null);

        //Add the view to the window.
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,      // | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSLUCENT);

        //Specify the view position
        params.gravity = Gravity.TOP | Gravity.LEFT;        //Initially view will be added to top-left corner | Gravity.CENTER_VERTICAL|Gravity.END;
        params.x = 0;
        params.y = 100;

        //Add the view to the window
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        if (mWindowManager != null) {
            mWindowManager.addView(mView, params);
        }

        ((ImageButton) mView.findViewById(R.id.btnClose)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Open the application  click.
                Intent intent = new Intent(CallAccessibilityService.this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
                //close the service and remove view from the view hierarchy
                stopSelf();
            }
        });

        ((ImageButton) mView.findViewById(R.id.btnStartRecording)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startRecording();
                Toast.makeText(CallAccessibilityService.this, "Playing", Toast.LENGTH_SHORT).show();
            }
        });
        ((ImageButton) mView.findViewById(R.id.btnStopRecording)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopRecording();
                Toast.makeText(CallAccessibilityService.this, "Stopping", Toast.LENGTH_SHORT).show();
            }
        });

        //Drag and move floating view using user's touch action.
        ((ImageButton) mView.findViewById(R.id.draggable_button)).setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //params.x = (int) event.getX();
                //params.y = (int) event.getY();

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //remember the initial position.
                        initialX = params.x;
                        initialY = params.y;
                        //get the touch location
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        int xDiff = (int) (event.getRawX() - initialTouchX);
                        int yDiff = (int) (event.getRawY() - initialTouchY);
                        //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little while clicking.
                        //So that is click event.
                        if (xDiff < 10 && yDiff < 10) {
                            Toast.makeText(CallAccessibilityService.this, "ACTION_UP", Toast.LENGTH_SHORT).show();
                        }
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        //Calculate the X and Y coordinates of the view.
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);
                        //Update the layout with new X & Y coordinate
                        mWindowManager.updateViewLayout(mView, params);
                        return true;
                }
                return false;
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mView != null) mWindowManager.removeView(mView);
    }

    public void startRecording() {
        try {
            String path = getApplicationContext().getFilesDir().getPath();
            //String selectedPath = Environment.getExternalStorageDirectory() + "/Testing";
            //String selectedPath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/Android/data/" + packageName + "/system_sound";

            File file = new File(path);
            if (!file.exists()){
                file.mkdirs();
            }

            mRecorder = new MediaRecorder();
            mRecorder.reset();


            //android.permission.RECORD_AUDIO
            String manufacturer = Build.MANUFACTURER;
            Log.d(TAG, manufacturer);
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //MIC | VOICE_COMMUNICATION (Android 10 release) | VOICE_RECOGNITION | (VOICE_CALL = VOICE_UPLINK + VOICE_DOWNLINK)
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //THREE_GPP | MPEG_4
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //AMR_NB | AAC


            String mFilePath = file + "/" + "REC_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".3gp"; //.3gp | .mp3
            mRecorder.setOutputFile(mFilePath);
            mRecorder.prepare();
            mRecorder.start();
            isStarted = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stopRecording() {
        if (isStarted && mRecorder != null) {
            mRecorder.stop();
            mRecorder.reset(); // You can reuse the object by going back to setAudioSource() step
            mRecorder.release();
            mRecorder = null;
            isStarted = false;
        }
    }


    }


}
© www.soinside.com 2019 - 2024. All rights reserved.