Skip to content

Commit dd96bfc

Browse files
committed
release 1.7.0
1 parent 3e9210d commit dd96bfc

File tree

18 files changed

+115
-62
lines changed

18 files changed

+115
-62
lines changed

Android/app/build.gradle

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ plugins {
44
}
55

66
android {
7-
compileSdkVersion 30
7+
compileSdkVersion 31
88
buildToolsVersion "30.0.3"
99

1010
defaultConfig {
1111
applicationId "com.example.microphone"
1212
minSdkVersion 23
13-
targetSdkVersion 30
13+
targetSdkVersion 31
1414
versionCode 6
15-
versionName "1.6"
15+
versionName "1.7"
1616

1717
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1818
}
@@ -35,13 +35,13 @@ android {
3535
dependencies {
3636

3737
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
38-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
38+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
3939
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
40-
implementation 'androidx.core:core-ktx:1.3.1'
41-
implementation 'androidx.appcompat:appcompat:1.2.0'
42-
implementation 'com.google.android.material:material:1.2.1'
43-
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
44-
testImplementation 'junit:junit:4.+'
45-
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
46-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
40+
implementation 'androidx.core:core-ktx:1.7.0'
41+
implementation 'androidx.appcompat:appcompat:1.4.1'
42+
implementation 'com.google.android.material:material:1.6.0'
43+
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
44+
testImplementation 'junit:junit:'
45+
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
46+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
4747
}

Android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package="com.example.microphone">
44
<uses-permission android:name="android.permission.BLUETOOTH" />
55
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
6+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
67
<uses-permission android:name="android.permission.RECORD_AUDIO" />
78
<uses-permission android:name="android.permission.INTERNET" />
89
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -16,7 +17,8 @@
1617
android:theme="@style/Theme.Microphone"
1718
android:name=".DefaultApp">
1819
<activity
19-
android:name=".MainActivity">
20+
android:name=".MainActivity"
21+
android:exported="true">
2022
<intent-filter>
2123
<action android:name="android.intent.action.MAIN" />
2224
<action android:name="android.intent.action.VIEW" />

Android/app/src/main/java/com/example/microphone/MainActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ class MainActivity : AppCompatActivity()
9191
// check for audio permission
9292
if(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
9393
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), 0)
94+
if(ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED)
95+
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.BLUETOOTH), 0)
96+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
97+
if(ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED)
98+
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.BLUETOOTH_CONNECT), 0)
99+
}
94100
// start handler thread
95101
handlerThread = HandlerThread("MicActivityStart", Process.THREAD_PRIORITY_BACKGROUND)
96102
handlerThread.start()

Android/app/src/main/java/com/example/microphone/audio/AudioBuffer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import kotlinx.coroutines.sync.withLock
66
class AudioBuffer
77
{
88
// set buffer size for latency
9-
private val BUFFER_SIZE = 2
9+
private val BUFFER_SIZE = 3
1010
// actual buffer of byte arrays (FIFO with queue)
1111
private val buffer = ArrayDeque<ByteArray>()
1212
// mutex for coroutines

Android/app/src/main/java/com/example/microphone/audio/MicAudioManager.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.Manifest
44
import android.content.Context
55
import android.content.pm.PackageManager
66
import android.media.AudioFormat
7-
import android.media.AudioManager
87
import android.media.AudioRecord
98
import android.media.MediaRecorder
109
import android.util.Log
@@ -42,8 +41,6 @@ class MicAudioManager(ctx : Context) {
4241
require(ContextCompat.checkSelfPermission(ctx, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED){
4342
"Microphone recording is not permitted"
4443
}
45-
// setup noise suppression
46-
(ctx.getSystemService(Context.AUDIO_SERVICE) as AudioManager).setParameters("noise_suppression=auto")
4744
// init recorder
4845
recorder = AudioRecord(AUDIO_SOURCE, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE)
4946
require(recorder?.state == AudioRecord.STATE_INITIALIZED){"Microphone not init properly"}
@@ -53,7 +50,7 @@ class MicAudioManager(ctx : Context) {
5350
suspend fun record(audioBuffer : AudioBuffer)
5451
{
5552
// read number of shorts
56-
val size = recorder?.read(buffer, 0, BUFFER_SIZE, AudioRecord.READ_BLOCKING) ?: return
53+
val size = recorder?.read(buffer, 0, BUFFER_SIZE) ?: return
5754
if(size <= 0)
5855
{
5956
delay(RECORD_DELAY)

Android/app/src/main/java/com/example/microphone/service/ForegroundService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ class ForegroundService : Service() {
379379
val onTap = Intent(ctx, MainActivity::class.java).apply {
380380
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
381381
}
382-
val pendingIntent = PendingIntent.getActivity(ctx, 0, onTap, 0)
382+
val pendingIntent = PendingIntent.getActivity(ctx, 0, onTap, PendingIntent.FLAG_IMMUTABLE)
383383
val builder = NotificationCompat.Builder(ctx, "AndroidMic")
384384
.setSmallIcon(R.drawable.icon)
385385
.setContentTitle(getString(R.string.activity_name))

Android/app/src/main/java/com/example/microphone/streaming/BluetoothStreamer.kt

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
package com.example.microphone.streaming
22

33
import android.Manifest
4-
import android.bluetooth.BluetoothAdapter
5-
import android.bluetooth.BluetoothClass
6-
import android.bluetooth.BluetoothDevice
7-
import android.bluetooth.BluetoothSocket
4+
import android.bluetooth.*
85
import android.content.BroadcastReceiver
96
import android.content.Context
107
import android.content.Intent
118
import android.content.IntentFilter
129
import android.content.pm.PackageManager
10+
import android.os.Build
1311
import android.util.Log
1412
import androidx.core.content.ContextCompat
1513
import com.example.microphone.audio.AudioBuffer
@@ -26,7 +24,7 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
2624
private val myUUID : UUID = UUID.fromString("34335e34-bccf-11eb-8529-0242ac130003")
2725
private val MAX_WAIT_TIME = 1500L // timeout
2826

29-
private val adapter : BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
27+
private val adapter : BluetoothAdapter
3028
private var target : BluetoothDevice? = null
3129
private var socket : BluetoothSocket? = null
3230

@@ -51,12 +49,20 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
5149
// init everything
5250
init
5351
{
52+
// get bluetooth adapter
53+
val bm = ctx.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
54+
adapter = bm.adapter
5455
// check bluetooth adapter
5556
require(adapter != null) {"Bluetooth adapter is not found"}
5657
// check permission
5758
require(ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED){
5859
"Bluetooth is not permitted"
5960
}
61+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
62+
require(ContextCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED){
63+
"Bluetooth is not permitted"
64+
}
65+
}
6066
require(adapter.isEnabled){"Bluetooth adapter is not enabled"}
6167
// set target device
6268
selectTargetDevice()
@@ -77,13 +83,21 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
7783
} catch (e : IOException) {
7884
Log.d(TAG, "connect [createInsecureRfcommSocketToServiceRecord]: ${e.message}")
7985
null
86+
} catch (e : SecurityException)
87+
{
88+
Log.d(TAG, "connect [createInsecureRfcommSocketToServiceRecord]: ${e.message}")
89+
null
8090
} ?: return false
8191
// connect to server
8292
try {
8393
socket?.connect()
8494
} catch (e : IOException){
8595
Log.d(TAG, "connect [connect]: ${e.message}")
8696
return false
97+
} catch (e : SecurityException)
98+
{
99+
Log.d(TAG, "connect [connect]: ${e.message}")
100+
return false
87101
}
88102
Log.d(TAG, "connect: connected")
89103
return true
@@ -136,22 +150,28 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
136150
private fun selectTargetDevice()
137151
{
138152
target = null
139-
val pairedDevices = adapter?.bondedDevices ?: return
140-
for(device in pairedDevices)
141-
{
142-
if(device.bluetoothClass.majorDeviceClass == BluetoothClass.Device.Major.COMPUTER)
153+
try {
154+
val pairedDevices = adapter.bondedDevices ?: return
155+
for(device in pairedDevices)
143156
{
144-
Log.d(TAG, "selectTargetDevice: testing ${device.name}")
145-
if(testConnection(device))
157+
if(device.bluetoothClass.majorDeviceClass == BluetoothClass.Device.Major.COMPUTER)
146158
{
147-
target = device
148-
Log.d(TAG, "selectTargetDevice: ${device.name} is valid")
149-
break
159+
Log.d(TAG, "selectTargetDevice: testing ${device.name}")
160+
if(testConnection(device))
161+
{
162+
target = device
163+
Log.d(TAG, "selectTargetDevice: ${device.name} is valid")
164+
break
165+
}
166+
else
167+
Log.d(TAG, "selectTargetDevice: ${device.name} is invalid")
150168
}
151-
else
152-
Log.d(TAG, "selectTargetDevice: ${device.name} is invalid")
153169
}
170+
} catch(e : SecurityException)
171+
{
172+
Log.d(TAG, "selectTargetDevice: ${e.message}")
154173
}
174+
155175
}
156176

157177
// test connection with a device
@@ -165,13 +185,21 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
165185
} catch (e : IOException) {
166186
Log.d(TAG, "testConnection [createInsecureRfcommSocketToServiceRecord]: ${e.message}")
167187
null
188+
} catch (e : SecurityException)
189+
{
190+
Log.d(TAG, "testConnection [createInsecureRfcommSocketToServiceRecord]: ${e.message}")
191+
null
168192
} ?: return false
169193
// try to connect
170194
try {
171195
socket.connect()
172196
} catch (e : IOException){
173197
Log.d(TAG, "testConnection [connect]: ${e.message}")
174198
return false
199+
} catch (e : SecurityException)
200+
{
201+
Log.d(TAG, "testConnection [connect]: ${e.message}")
202+
return false
175203
}
176204
var isValid = false
177205
runBlocking(Dispatchers.IO) {
@@ -215,8 +243,15 @@ class BluetoothStreamer(private val ctx : Context) : Streamer {
215243
// get connected device information
216244
override fun getInfo() : String
217245
{
218-
if(adapter == null || target == null || socket == null) return ""
219-
return "[Device Name] ${target?.name}\n[Device Address] ${target?.address}"
246+
if(target == null || socket == null) return ""
247+
val deviceName = try {
248+
target?.name
249+
} catch (e : SecurityException)
250+
{
251+
Log.d(TAG, "getInfo: ${e.message}")
252+
"null"
253+
}
254+
return "[Device Name] ${deviceName}\n[Device Address] ${target?.address}"
220255
}
221256

222257
// return true if is connected for streaming

Android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ buildscript {
66
mavenCentral()
77
}
88
dependencies {
9-
classpath 'com.android.tools.build:gradle:7.0.0'
9+
classpath 'com.android.tools.build:gradle:7.1.3'
1010
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1111

1212
// NOTE: Do not place your application dependencies here; they belong
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Mon May 24 15:46:59 EDT 2021
22
distributionBase=GRADLE_USER_HOME
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
44
distributionPath=wrapper/dists
55
zipStorePath=wrapper/dists
66
zipStoreBase=GRADLE_USER_HOME

Assets/p1.png

17.4 KB
Loading

0 commit comments

Comments
 (0)