Skip to content

Commit

Permalink
Android 14 Support added
Browse files Browse the repository at this point in the history
- Ported InputManagerGlobalEventInjector to support input event for Android 14
- Fixed crash SonicKeyboard on Android 14 because behavior changes of registerReceiver method
- Fixed crash SonicManagerServiceV2 on Android 14 because behavior changes of startForeground method
- Updated targetSdk and compileSdk to 34
- Updated AGP to 8.2.2 and Gradle 8.6
- Removed duplicate permissions
  • Loading branch information
hazmi-e205 committed Feb 22, 2024
1 parent 2db215e commit 13ce264
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 24 deletions.
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ plugins {
}

android {
compileSdk 31
compileSdk 34
namespace "org.cloud.sonic.android"

defaultConfig {
applicationId "org.cloud.sonic.android"
minSdk 21
targetSdk 31
targetSdk 34
versionCode 10
versionName "SONIC_VERSION"

Expand Down
14 changes: 7 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.cloud.sonic.android">
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 获取wifi需要 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Expand All @@ -23,8 +21,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
Expand All @@ -33,7 +29,10 @@
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- Needed for Android 14 (API level 34) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />

<application
android:name=".App"
Expand Down Expand Up @@ -98,7 +97,8 @@

<service
android:name=".service.SonicManagerServiceV2"
android:exported="true" />
android:exported="true"
android:foregroundServiceType="mediaPlayback" />

<service
android:name=".plugin.SonicPluginAudioService"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import android.app.Activity
import android.content.*
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.inputmethodservice.InputMethodService
import android.os.Build
import android.provider.Settings
import android.view.KeyEvent
import android.view.View
Expand Down Expand Up @@ -61,7 +62,11 @@ class SonicKeyboard : InputMethodService() {
filter.addAction(IME_RECOVER_CLIPBOARD_GET)
filter.addAction(IME_RECOVER_CLIPBOARD_SET)
mReceiver = AdbReceiver()
registerReceiver(mReceiver, filter)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerReceiver(mReceiver, filter, RECEIVER_EXPORTED)
} else {
registerReceiver(mReceiver, filter)
}
}
mInputView.setOnClickListener {
val intent = Intent(Settings.ACTION_INPUT_METHOD_SETTINGS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ class InputManagerWrapper {

init {
eventInjector = try {
InputManagerEventInjector()
InputManagerGlobalEventInjector()
} catch (e: UnsupportedOperationException) {
WindowManagerEventInjector()
try {
InputManagerEventInjector()
} catch (e: UnsupportedOperationException) {
WindowManagerEventInjector()
}
}
}

Expand All @@ -48,6 +52,65 @@ class InputManagerWrapper {
fun injectInputEvent(event: InputEvent?): Boolean
}

class InputManagerGlobalEventInjector : EventInjector {
private val injectMode = 0
private var inputManager: Any? = null
private var injector: Method? = null

init {
try {
var inputManagerGlobal = getInstance("android.hardware.input.InputManagerGlobal");
var m = inputManagerGlobal?.javaClass?.getMethod("getInputManagerService");
inputManager = m?.invoke(inputManagerGlobal);
injector = inputManager?.javaClass
?.getMethod(
"injectInputEvent",
InputEvent::class.java,
Int::class.javaPrimitiveType
);
}
catch (e: NoSuchMethodException) {
throw java.lang.UnsupportedOperationException(
"InputManagerEventInjector is not supported in this device! " +
"Please submit your deviceInfo to https://github.com/SonicCloudOrg/sonic-android-apk"
)
}
catch (e: InvocationTargetException) {
throw java.lang.UnsupportedOperationException(
"InputManagerEventInjector is not supported in this device! " +
"Please submit your deviceInfo to https://github.com/SonicCloudOrg/sonic-android-apk"
)
}
catch (e: IllegalAccessException) {
throw java.lang.UnsupportedOperationException(
"InputManagerEventInjector is not supported in this device! " +
"Please submit your deviceInfo to https://github.com/SonicCloudOrg/sonic-android-apk"
)
}
}
private fun getInstance(className: String): Any {
val aClass = Class.forName(className)
val getInstance = aClass.getMethod("getInstance")
return getInstance.invoke(null)
}
override fun injectInputEvent(event: InputEvent?): Boolean {
return try {
injector!!.invoke(
inputManager,
event,
injectMode
)
true
} catch (e: IllegalAccessException) {
e.printStackTrace()
false
} catch (e: InvocationTargetException) {
e.printStackTrace()
false
}
}
}

class InputManagerEventInjector : EventInjector {
private val injectMode = 0
private var inputManager: Any? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package org.cloud.sonic.android.service
import android.app.*
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.graphics.drawable.Icon
import android.os.*
import androidx.annotation.RequiresApi
Expand Down Expand Up @@ -78,6 +79,14 @@ class SonicManagerServiceV2 : Service(), TcpServerListener {
}
}

fun StartForeground(id: Int, notification: Notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
} else {
startForeground(NOTIFICATION_ID, notification)
}
}

override fun onCreate() {
super.onCreate()
LogUtils.i("onCreate")
Expand All @@ -91,15 +100,12 @@ class SonicManagerServiceV2 : Service(), TcpServerListener {
NotificationManager.IMPORTANCE_NONE
)
getNotificationManager().createNotificationChannel(channel)
startForeground(
NOTIFICATION_ID,
notification
)
StartForeground(NOTIFICATION_ID, notification)
} else {
// 获取服务通知
val notification: Notification = createNotification(false)
//将服务置于启动状态 ,NOTIFICATION_ID指的是创建的通知的ID
startForeground(NOTIFICATION_ID, notification)
StartForeground(NOTIFICATION_ID, notification)
}
}

Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ buildscript {


plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'com.android.application' version '8.2.2' apply false
id 'com.android.library' version '8.2.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
5 changes: 3 additions & 2 deletions lib_socketmanager/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ plugins {
}

android {
compileSdk 32
compileSdk 34
namespace "org.cloud.sonic.android.lib.socketmanager"

defaultConfig {
minSdk 21
targetSdk 32
targetSdk 34

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
Expand Down
3 changes: 1 addition & 2 deletions lib_socketmanager/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.cloud.sonic.android.lib.socketmanager">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>

0 comments on commit 13ce264

Please sign in to comment.