Last active
April 16, 2025 04:39
-
-
Save dragonlord2025/86b05ae10dbd6456aa53 to your computer and use it in GitHub Desktop.
Recording From Bluetooth Headset
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example.audiogain; | |
| import android.app.Activity; | |
| import android.bluetooth.BluetoothAdapter; | |
| import android.content.BroadcastReceiver; | |
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.content.IntentFilter; | |
| import android.content.SharedPreferences; | |
| import android.media.AudioManager; | |
| import android.os.CountDownTimer; | |
| import android.widget.Toast; | |
| public class Recording { | |
| static int count = 0; | |
| static String Shared; | |
| static String bFlag; | |
| public static int TIMEOUT = 5000; | |
| public static int COUNTDOWN_INTERVAL = 1000; | |
| static Context context; | |
| public static void checkAndRecord(Context context, | |
| OnBluetoothRecording BluetoothRecording, boolean resume) { | |
| // Check bluetooth flag And Bluetooth is ON or OFF | |
| if (getBluetoothFlag(context) && isBluetoothON()) { | |
| // Check for bluetooth and Record | |
| startBluetoothRecording(BluetoothRecording, resume, context); | |
| } else { | |
| // If Bluetooth is OFF Show Toast else Dont Show | |
| if (getBluetoothFlag(context) && !isBluetoothON()) { | |
| // false because recording not started | |
| Toast.makeText(context, | |
| "Bluetooth is OFF. Recording from Phone MIC.", | |
| Toast.LENGTH_SHORT).show(); | |
| BluetoothRecording.onStartRecording(resume, false); | |
| } else { | |
| // false because recording not started | |
| BluetoothRecording.onStartRecording(resume, false); | |
| } | |
| } | |
| } | |
| private static void startBluetoothRecording( | |
| final OnBluetoothRecording BluetoothRecording, | |
| final boolean resume, Context context) { | |
| // TODO Auto-generated method stub | |
| final int MAX_ATTEPTS_TO_CONNECT = 3; | |
| final AudioManager audioManager = (AudioManager) context | |
| .getSystemService(Context.AUDIO_SERVICE); | |
| final CountDownTimer timer = getTimer(BluetoothRecording, audioManager, | |
| resume); | |
| context.registerReceiver(new BroadcastReceiver() { | |
| @Override | |
| public void onReceive(Context context, Intent intent) { | |
| int state = intent.getIntExtra( | |
| AudioManager.EXTRA_SCO_AUDIO_STATE, -1); | |
| if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { | |
| // cancel Timer | |
| timer.cancel(); | |
| context.unregisterReceiver(this); | |
| // pass through and true because | |
| // recording from bluetooth so set 8000kHz | |
| BluetoothRecording.onStartRecording(resume, true); | |
| } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) { | |
| if (count > MAX_ATTEPTS_TO_CONNECT) { | |
| context.unregisterReceiver(this); | |
| // Stop BluetoothSCO | |
| audioManager.stopBluetoothSco(); | |
| // reset Counter | |
| count = 0; | |
| // stop timer | |
| timer.cancel(); | |
| // false because still recording not started | |
| BluetoothRecording.onStartRecording(resume, false); | |
| } else { | |
| // Increment Disconnect state Count | |
| count++; | |
| } | |
| } | |
| } | |
| }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); | |
| // Start the timer | |
| timer.start(); | |
| audioManager.startBluetoothSco(); | |
| } | |
| // set the Timeout | |
| private static CountDownTimer getTimer( | |
| final OnBluetoothRecording BluetoothRecording, | |
| final AudioManager audioManager, final boolean resume) { | |
| // TODO Auto-generated method stub | |
| return new CountDownTimer(TIMEOUT, COUNTDOWN_INTERVAL) { | |
| @Override | |
| public void onTick(long millisUntilFinished) { | |
| // Do Nothing | |
| } | |
| @Override | |
| public void onFinish() { | |
| // stopBluetoothSCO() and start Normal Recording | |
| audioManager.stopBluetoothSco(); | |
| // false because recording button is already clicked but still | |
| // not recording. | |
| BluetoothRecording.onStartRecording(resume, false); | |
| } | |
| }; | |
| } | |
| // Return's the bluetooth state | |
| private static boolean isBluetoothON() { | |
| BluetoothAdapter bluetoothAdapter = BluetoothAdapter | |
| .getDefaultAdapter(); | |
| return bluetoothAdapter.isEnabled(); | |
| } | |
| // Return's the bluetoothFlag state | |
| private static boolean getBluetoothFlag(Context context) { | |
| // shared pref | |
| SharedPreferences sp = context.getSharedPreferences(Shared, | |
| Context.MODE_PRIVATE); | |
| return sp.getBoolean(bFlag, false); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great working for me be low is my code
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.os.Binder;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.ServiceCompat;
import androidx.lifecycle.MutableLiveData;
import com.dev.auditiontech.R;
import com.dev.auditiontech.activity.MainActivity;
public class MonitorServiceMic extends Service {
private static final String TAG = "MonitorServiceMic";
public static MonitorServiceMic service;
private NotificationManager nm;
private NotificationCompat.Builder nCB;
private static final String CHANNEL_ID = "MonitoringChannel";
private static final int NOTIFICATION_ID = 1001;
private AudioRecord audioRecord;
private AudioManager audioManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothHeadset bluetoothHeadset;
private String micSourceName = "";
private boolean isBluetoothMic = false;
private BluetoothDevice connectedBluetoothDevice = null;
private double lastDecibel = 0.0;
private String lastSafeFor = "N/A";
private double lastNotifiedDecibel = -1.0;
private String lastNotifiedSafeFor = "";
private final IBinder binderMic = new LocalBinder();
private Handler micUpdateHandler;
private MutableLiveData volume = new MutableLiveData<>();
private boolean isRecording = false;
private boolean isInitializing = false;
private static final int SAMPLE_RATE = 8000; // Optimized for Bluetooth
private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT) * 2;
private static final double BASE = 32767.0; // Max amplitude for 16-bit PCM
private static final long RECONNECT_DELAY_MS = 5000;
private static final int SCO_TIMEOUT_MS = 5000;
private static final int SCO_COUNTDOWN_INTERVAL_MS = 1000;
private static final int MAX_SCO_ATTEMPTS = 3;
}