diff --git a/app/build.gradle b/app/build.gradle index 2babf38..45eb895 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.github.axet.audiorecorder" minSdkVersion 9 targetSdkVersion 23 // 24+ file:// unable to open - versionCode 232 - versionName "3.1.2" + versionCode 233 + versionName "3.1.3" } signingConfigs { release { 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 33964d5..e346804 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 @@ -51,12 +51,17 @@ import com.github.axet.audiolibrary.widgets.PitchView; import com.github.axet.audiorecorder.R; import com.github.axet.audiorecorder.app.MainApplication; import com.github.axet.audiorecorder.app.Storage; +import com.github.axet.audiorecorder.services.BluetoothReceiver; import com.github.axet.audiorecorder.services.RecordingService; import java.io.File; import java.nio.ShortBuffer; import java.util.concurrent.atomic.AtomicBoolean; +import static android.media.AudioManager.SCO_AUDIO_STATE_CONNECTED; +import static android.media.AudioManager.SCO_AUDIO_STATE_CONNECTING; +import static android.media.AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + public class RecordingActivity extends AppCompatActivity { public static final String TAG = RecordingActivity.class.getSimpleName(); @@ -121,60 +126,34 @@ public class RecordingActivity extends AppCompatActivity { context.startActivity(i); } - class RecordingReceiver extends BroadcastReceiver { - boolean bluetoothSource = false; // are we using bluetooth source recording - boolean bluetoothStart = false; // did we start already? - boolean pausedByBluetooth = false; - boolean pause = false; // resumed recording by user, show error only on user actions + class RecordingReceiver extends BluetoothReceiver { - Runnable connected = new Runnable() { - @Override - public void run() { - handler.removeCallbacks(connected); - if (pausedByBluetooth) { - pausedByBluetooth = false; - if (thread == null) { - if (isRecordingReady()) - startRecording(); - } - } - } - }; + public RecordingReceiver(Context context) { + super(context); + } - Runnable disconnected = new Runnable() { - @Override - public void run() { - handler.removeCallbacks(connected); - if (thread != null) { - pausedByBluetooth = true; - stopRecording(getString(R.string.hold_by_bluetooth)); - stopBluetooth(); - } else { - if (pause) { - pause = false; - Toast.makeText(RecordingActivity.this, R.string.hold_by_bluetooth, Toast.LENGTH_SHORT).show(); - } - } + @Override + public void onConnected() { + if (thread == null) { + if (isRecordingReady()) + startRecording(); } - }; + } + + @Override + public void onDisconnected() { + if (thread != null) { + stopRecording(getString(R.string.hold_by_bluetooth)); + super.onDisconnected(); + } + } @Override public void onReceive(final Context context, Intent intent) { + super.onReceive(context, intent); String a = intent.getAction(); if (a == null) return; - if (bluetoothSource && a.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { - handler.postDelayed(connected, 3000); // give os time ot initialize device, or startBluetoothSco will be ignored - } - if (bluetoothSource && a.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { - int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); - if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { - connected.run(); - } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) { - disconnected.run(); - } - return; - } if (a.equals(PAUSE_BUTTON)) { pauseButton(); return; @@ -202,7 +181,7 @@ public class RecordingActivity extends AppCompatActivity { break; case TelephonyManager.CALL_STATE_IDLE: if (pausedByCall) { - if (isRecordingReady()) + if (receiver.isRecordingReady()) startRecording(); } wasRinging = false; @@ -337,7 +316,7 @@ public class RecordingActivity extends AppCompatActivity { stopRecording(getString(R.string.recording_status_pause)); } - receiver = new RecordingReceiver(); + receiver = new RecordingReceiver(this); IntentFilter filter = new IntentFilter(); filter.addAction(PAUSE_BUTTON); filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); @@ -396,46 +375,20 @@ public class RecordingActivity extends AppCompatActivity { void pauseButton() { if (thread != null) { + receiver.pause = false; stopRecording(getString(R.string.recording_status_pause)); - stopBluetooth(); + receiver.stopBluetooth(); headset(true, false); } else { receiver.pause = true; - stopBluetooth(); // reset bluetooth + receiver.stopBluetooth(); // reset bluetooth editCut(); - if (isRecordingReady()) { + if (receiver.isRecordingReady()) { startRecording(); } } } - boolean startBluetooth() { - AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (am.isBluetoothScoAvailableOffCall()) { - if (!receiver.bluetoothStart) { - am.startBluetoothSco(); - receiver.bluetoothStart = true; - } - if (!am.isBluetoothScoOn()) { - receiver.pausedByBluetooth = true; - return false; - } - } - return true; - } - - public boolean isRecordingReady() { - final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this); - if (shared.getString(MainApplication.PREFERENCE_BLUETOOTH, MainApplication.SOURCE_MIC).equals(MainApplication.SOURCE_BLUETOOTH)) { - receiver.bluetoothSource = true; - if (!startBluetooth()) - return false; - } else { - receiver.bluetoothSource = false; - } - return true; - } - @Override protected void onResume() { super.onResume(); @@ -447,7 +400,7 @@ public class RecordingActivity extends AppCompatActivity { if (start) { start = false; if (Storage.permitted(this, PERMISSIONS_AUDIO, RESULT_START)) { // audio perm - if (isRecordingReady()) + if (receiver.isRecordingReady()) startRecording(); else stopRecording(getString(R.string.hold_by_bluetooth)); @@ -695,22 +648,13 @@ public class RecordingActivity extends AppCompatActivity { dialog.show(); } - public void stopBluetooth() { - handler.removeCallbacks(receiver.connected); - AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (receiver.bluetoothStart) { - receiver.bluetoothStart = false; - am.stopBluetoothSco(); - } - } - @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestory"); stopRecording(); - stopBluetooth(); + receiver.stopBluetooth(); headset(false, false); if (receiver != null) { @@ -973,7 +917,7 @@ public class RecordingActivity extends AppCompatActivity { switch (requestCode) { case RESULT_START: if (Storage.permitted(this, permissions)) { - if (isRecordingReady()) + if (receiver.isRecordingReady()) startRecording(); } else { Toast.makeText(this, R.string.not_permitted, Toast.LENGTH_SHORT).show(); 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 new file mode 100644 index 0000000..bd64c8f --- /dev/null +++ b/app/src/main/java/com/github/axet/audiorecorder/services/BluetoothReceiver.java @@ -0,0 +1,129 @@ +package com.github.axet.audiorecorder.services; + +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.media.AudioManager; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.widget.Toast; + +import com.github.axet.audiorecorder.R; +import com.github.axet.audiorecorder.activities.RecordingActivity; +import com.github.axet.audiorecorder.app.MainApplication; + +// default bluetooth stack for API25, bugged and has to be cleared. +public class BluetoothReceiver extends BroadcastReceiver { + + public static int CONNECT_DELAY = 3000; // give os time ot initialize device, or startBluetoothSco will be ignored + + public Context context; + public Handler handler = new Handler(); + public boolean bluetoothSource = false; // are we using bluetooth source recording + public boolean bluetoothStart = false; // did we start already? + public boolean pausedByBluetooth = false; + public boolean pause = false; // resumed recording by user, show error only on user actions + public boolean connecting = false; + + public Runnable connected = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(connected); + if (pausedByBluetooth) { + pausedByBluetooth = false; + onConnected(); + } + } + }; + + public Runnable disconnected = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(connected); + onDisconnected(); + if (pause) { + pause = false; + Toast.makeText(context, R.string.hold_by_bluetooth, Toast.LENGTH_SHORT).show(); + } + if (connecting) { + connecting = false; + stopBluetooth(); + } + } + }; + + public BluetoothReceiver(Context context) { + this.context = context; + } + + public void onConnected() { + } + + public void onDisconnected() { + pausedByBluetooth = true; + stopBluetooth(); + } + + @Override + public void onReceive(Context context, Intent intent) { + String a = intent.getAction(); + if (a == null) + return; + 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) { + case AudioManager.SCO_AUDIO_STATE_CONNECTED: + connected.run(); + break; + case AudioManager.SCO_AUDIO_STATE_CONNECTING: + connecting = true; + break; + case AudioManager.SCO_AUDIO_STATE_DISCONNECTED: + disconnected.run(); + break; + } + } + } + + boolean startBluetooth() { + AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + if (am.isBluetoothScoAvailableOffCall()) { + if (!bluetoothStart) { + am.startBluetoothSco(); + bluetoothStart = true; + } + if (!am.isBluetoothScoOn()) { + pausedByBluetooth = true; + return false; + } + } + return true; + } + + public void stopBluetooth() { + handler.removeCallbacks(connected); + AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + if (bluetoothStart) { + bluetoothStart = false; + am.stopBluetoothSco(); + } + } + + public boolean isRecordingReady() { + final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context); + if (shared.getString(MainApplication.PREFERENCE_BLUETOOTH, MainApplication.SOURCE_MIC).equals(MainApplication.SOURCE_BLUETOOTH)) { + bluetoothSource = true; + if (!startBluetooth()) + return false; + } else { + bluetoothSource = false; + } + return true; + } + +}