diff --git a/Android/README.md b/Android/README.md index 13bea52..301424f 100644 --- a/Android/README.md +++ b/Android/README.md @@ -6,9 +6,10 @@ Android Microphone Project (Android Application folder) ### Structure -Three major threads: +Four major threads: * UI thread * Bluetooth client thread +* USB tcp client thread * Audio recorder thread ------ @@ -27,6 +28,13 @@ Three major threads: * transfer stored audio data * cancel connection +#### USB Thread + +* check if USB tethering is enabled +* connect to server based on input address +* transfer stored audio data +* cancel connection + #### Audio Thread * check for permission @@ -40,4 +48,6 @@ Three major threads: This is the first Android application I write in Kotlin. The bluetooth part is basically the same as the Java applications I wrote before. However, Kotlin appears to be cleaner and shorter in length. A notable difference is that Kotlin uses `coroutines` to replace `AsyncTask` in Java, which I think is better. Another difference is that Kotlin is strict with `null` values and provide many ways to check them. -A drawback of this application is that it won't be able to run in background. So when connected, your application will force the screen on and will close connection whenever the app is put into background. A possible fix is to create [Background Services](https://developer.android.com/training/run-background-service/create-service) instead of threads I'm currently using. However, that requires much efforts in learning, and the communication with main activity is especially complex. I will leave it like that. \ No newline at end of file +A drawback of this application is that it won't be able to run in background. So when connected, your application will force the screen on and will close connection whenever the app is put into background. A possible fix is to create [Background Services](https://developer.android.com/training/run-background-service/create-service) instead of threads I'm currently using. However, that requires much efforts in learning, and the communication with main activity is especially complex. I will leave it like that. + +USB communication is achieved by enabling USB tethering. In this case, the network through PC can be detected by Android. By establishing a TCP socket, the device can communicate with PC app through USB. \ No newline at end of file diff --git a/Android/app/build.gradle b/Android/app/build.gradle index 18a97b6..901633b 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "com.example.microphone" minSdkVersion 19 targetSdkVersion 30 - versionCode 2 - versionName "1.1" + versionCode 3 + versionName "1.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml index bb3013d..dab343a 100644 --- a/Android/app/src/main/AndroidManifest.xml +++ b/Android/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + - + diff --git a/Android/app/src/main/java/com/example/microphone/BluetoothHelper.kt b/Android/app/src/main/java/com/example/microphone/BluetoothHelper.kt index 7d0f94b..a122e7c 100644 --- a/Android/app/src/main/java/com/example/microphone/BluetoothHelper.kt +++ b/Android/app/src/main/java/com/example/microphone/BluetoothHelper.kt @@ -222,6 +222,6 @@ class BluetoothHelper(private val mActivity: MainActivity, private val mGlobalDa // check if current socket is valid and connected fun isSocketValid() : Boolean { - return !(mSocket == null || mSocket?.isConnected == false) + return mSocket?.isConnected == true } } \ No newline at end of file diff --git a/Android/app/src/main/java/com/example/microphone/MainActivity.kt b/Android/app/src/main/java/com/example/microphone/MainActivity.kt index 08f5dca..f84d8fc 100644 --- a/Android/app/src/main/java/com/example/microphone/MainActivity.kt +++ b/Android/app/src/main/java/com/example/microphone/MainActivity.kt @@ -1,13 +1,17 @@ package com.example.microphone +import android.content.DialogInterface import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.text.InputType import android.util.Log import android.view.View import android.view.WindowManager import android.widget.Button +import android.widget.EditText import android.widget.TextView import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.SwitchCompat import kotlinx.coroutines.* import java.lang.Exception @@ -26,7 +30,10 @@ class GlobalState( var isBluetoothStarted : Boolean, var bluetoothShouldStop : Boolean, var isAudioStarted : Boolean, - var audioShouldStop : Boolean + var audioShouldStop : Boolean, + var isUSBStarted : Boolean, + var usbShouldStop : Boolean, + var isUSBAddressSet : Boolean ) // global data structure @@ -69,13 +76,18 @@ class MainActivity : AppCompatActivity() private val mUIScope = CoroutineScope(Dispatchers.Main) private var mJobBluetooth : Job? = null private var mJobAudio : Job? = null + private var mJobUSB : Job? = null private lateinit var mLogTextView : TextView private var helperBluetooth : BluetoothHelper? = null private var helperAudio : AudioHelper? = null + private var helperUSB : USBHelper? = null private val mGlobalState = GlobalState( + false, + false, + false, false, false, false, @@ -86,6 +98,7 @@ class MainActivity : AppCompatActivity() private var threadBth : Thread? = null private var threadAio : Thread? = null + private var threadUSB : Thread? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -99,31 +112,39 @@ class MainActivity : AppCompatActivity() override fun onStop() { super.onStop() - mGlobalState.bluetoothShouldStop = true - mGlobalState.audioShouldStop = true - threadBth?.join() - threadAio?.join() - helperBluetooth?.clean() - helperAudio?.clean() + clean() } override fun onResume() { super.onResume() findViewById