mirror of
https://github.com/basti564/Oculess.git
synced 2024-11-24 11:12:36 +01:00
BG Audio is now a service, more reliable & efficient
This commit is contained in:
parent
2ad14e7287
commit
c438acdd27
17
.idea/deploymentTargetDropDown.xml
Normal file
17
.idea/deploymentTargetDropDown.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\ethan\.android\avd\Pixel_3a_API_34_extension_level_7_x86_64.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-07-29T09:28:03.346931100Z" />
|
||||
</component>
|
||||
</project>
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
@ -34,7 +33,7 @@
|
||||
</option>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.bos.oculess"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 33
|
||||
versionCode 12
|
||||
versionName "1.4.0"
|
||||
versionCode 13
|
||||
versionName "1.5.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
@ -5,11 +5,9 @@
|
||||
<uses-feature android:glEsVersion="0x00030001" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<!-- the following is required for background audio to query 3rd party apps -->
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
|
||||
<application
|
||||
android:banner="@mipmap/ic_banner"
|
||||
@ -30,14 +28,14 @@
|
||||
android:resource="@xml/device_admin" />
|
||||
></receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".audio.BootDeviceReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<!-- <receiver-->
|
||||
<!-- android:name=".audio.BootDeviceReceiver"-->
|
||||
<!-- android:enabled="true"-->
|
||||
<!-- android:exported="true">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="android.intent.action.BOOT_COMPLETED"/>-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- </receiver>-->
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
@ -49,6 +47,20 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
<service
|
||||
android:name=".AudioService"
|
||||
android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.accessibilityservice"
|
||||
android:resource="@xml/accessibility_service_config" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
128
app/src/main/java/com/bos/oculess/AudioService.kt
Normal file
128
app/src/main/java/com/bos/oculess/AudioService.kt
Normal file
@ -0,0 +1,128 @@
|
||||
package com.bos.oculess
|
||||
|
||||
import android.accessibilityservice.AccessibilityService
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Handler
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.SettingNotFoundException
|
||||
import android.util.Log
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import com.bos.oculess.util.AppOpsUtil
|
||||
class AudioService : AccessibilityService() {
|
||||
companion object {
|
||||
private const val TAG = "OculessAudioService"
|
||||
private var audioApps: Array<String>? = null
|
||||
private var canUpdateAppList = true;
|
||||
fun isAccessibilityInitialized(context: Context): Boolean {
|
||||
try {
|
||||
Settings.Secure.getInt(
|
||||
context.applicationContext.contentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED
|
||||
)
|
||||
val settingValue = Settings.Secure.getString(
|
||||
context.applicationContext.contentResolver,
|
||||
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
|
||||
)
|
||||
if (settingValue != null) {
|
||||
return settingValue.contains(context.packageName)
|
||||
}
|
||||
} catch (e: SettingNotFoundException) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
fun requestAccessibility(context: Context) {
|
||||
val localIntent = Intent("android.settings.ACCESSIBILITY_SETTINGS")
|
||||
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
localIntent.setPackage("com.android.settings")
|
||||
context.startActivity(localIntent)
|
||||
}
|
||||
}
|
||||
override fun onAccessibilityEvent(e: AccessibilityEvent?) {
|
||||
if (e?.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
||||
Log.i(TAG, "Trigger: TYPE_WINDOW_STATE_CHANGED")
|
||||
checkUpdateAppList()
|
||||
audioFix()
|
||||
} else if (e?.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
|
||||
Log.i(TAG, "Trigger: TYPE_WINDOW_CONTENT_CHANGED")
|
||||
audioFix()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInterrupt() {
|
||||
Log.w(TAG, "Service Interrupted!")
|
||||
}
|
||||
|
||||
private fun checkUpdateAppList() {
|
||||
if (canUpdateAppList) {
|
||||
updateAudioPackages()
|
||||
val handler: Handler = Handler()
|
||||
canUpdateAppList = false
|
||||
handler.postDelayed(Runnable {
|
||||
canUpdateAppList = true
|
||||
Log.i(TAG, "Allowed to re-scan packages")
|
||||
}, 5000) //1s timeout before we're allowed to look for new packages
|
||||
}
|
||||
}
|
||||
|
||||
// Audio-specific
|
||||
private fun audioFix() {
|
||||
enableAudioPermission()
|
||||
|
||||
val handler: Handler = Handler()
|
||||
val r = Runnable {
|
||||
enableAudioPermission()
|
||||
}
|
||||
handler.postDelayed(r, 250)
|
||||
handler.postDelayed(r, 1500)
|
||||
}
|
||||
private fun updateAudioPackages() {
|
||||
Log.i(TAG, "Start package scan...")
|
||||
|
||||
if (applicationContext.packageManager == null) {
|
||||
Log.w(TAG, "applicationContext.packageManager is null!")
|
||||
return
|
||||
}
|
||||
/* Get All Installed Packages for Audio */
|
||||
// Requires query-all-packages permission
|
||||
val packageInfoList = applicationContext.packageManager?.getInstalledPackages(0)
|
||||
val packageNames = arrayListOf<String>()
|
||||
for (packageInfo in packageInfoList!!) {
|
||||
packageNames.add(packageInfo.packageName)
|
||||
}
|
||||
// Remove system apps
|
||||
val packageInfoListSystem = applicationContext.packageManager?.getInstalledPackages(
|
||||
PackageManager.MATCH_SYSTEM_ONLY)
|
||||
for (packageInfoSystem in packageInfoListSystem!!) {
|
||||
packageNames.remove(packageInfoSystem.packageName)
|
||||
}
|
||||
// Commit to app list
|
||||
audioApps = packageNames.toTypedArray()
|
||||
Log.i(TAG, "...end package scan")
|
||||
}
|
||||
|
||||
private fun enableAudioPermission() {
|
||||
Log.d(TAG, "Enabling permissions (This should run in bursts but not continuously)")
|
||||
|
||||
if (audioApps == null) {
|
||||
Log.i(TAG, "AudioApps is null!")
|
||||
return
|
||||
}
|
||||
var first = true
|
||||
for (app in audioApps!!) {
|
||||
val info: ApplicationInfo?= applicationContext.packageManager?.getApplicationInfo(app, 0)
|
||||
// https://cs.android.com/android/platform/superproject/+/master:frameworks/proto_logging/stats/enums/app/enums.proto;l=138?q=PLAY_AUDIO
|
||||
try {
|
||||
AppOpsUtil.allowOp(applicationContext, 28, info?.uid!!, app) // Play audio
|
||||
// AppOpsUtil.allowOp(applicationContext, 27, info?.uid!!, app) // Record audio
|
||||
} catch (e: java.lang.SecurityException) {
|
||||
Log.w(TAG, "Audio service lacks permission to set appops. Is Oculess device owner?")
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Enabled permissions (This should occur VERY shortly after enabling permissions)")
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.bos.oculess
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
@ -23,7 +25,7 @@ import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
// @RequiresApi(Build.VERSION_CODES.N)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
@ -255,11 +257,11 @@ class MainActivity : AppCompatActivity() {
|
||||
message.append("<b>")
|
||||
.append(it)
|
||||
.append("</b> is ")
|
||||
.append(if (dpm.isApplicationHidden(deviceAdminReceiverComponentName, it)) "disabled\r" else "<b>enabled</b>\r")
|
||||
.append(if (dpm.isApplicationHidden(deviceAdminReceiverComponentName, it)) "disabled\r" else "ENABLED\r")
|
||||
}
|
||||
val builder1: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
builder1.setTitle(getString(R.string.title1))
|
||||
builder1.setMessage(Html.fromHtml(message.toString(), 0))
|
||||
builder1.setMessage(message.toString())
|
||||
builder1.setPositiveButton(
|
||||
getString(R.string.ok)
|
||||
) { dialog, _ ->
|
||||
@ -299,11 +301,39 @@ class MainActivity : AppCompatActivity() {
|
||||
audioBtn.setOnClickListener {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
builder.setTitle(getString(R.string.title0))
|
||||
builder.setMessage(getString(R.string.audio_info))
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.ok)
|
||||
) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
if (!isOwner) {
|
||||
builder.setMessage(getString(R.string.audio_info_none))
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.ok)
|
||||
) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else if (!AudioService.isAccessibilityInitialized(applicationContext)) {
|
||||
builder.setMessage(getString(R.string.audio_info_serv))
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.ok)
|
||||
) { dialog, _ ->
|
||||
AudioService.requestAccessibility(applicationContext)
|
||||
dialog.dismiss()
|
||||
}
|
||||
builder.setNegativeButton(
|
||||
getString(R.string.cancel)
|
||||
) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
} else {
|
||||
builder.setMessage(getString(R.string.audio_info_done))
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.settings)
|
||||
) { dialog, _ ->
|
||||
AudioService.requestAccessibility(applicationContext)
|
||||
dialog.dismiss()
|
||||
}
|
||||
builder.setNegativeButton(
|
||||
getString(R.string.cancel)
|
||||
) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
val alertDialog: AlertDialog = builder.create()
|
||||
alertDialog.show()
|
||||
|
@ -1,86 +0,0 @@
|
||||
package com.bos.oculess.audio
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.bos.oculess.util.AppOpsUtil
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BootDeviceReceiver : BroadcastReceiver() {
|
||||
companion object {
|
||||
private const val TAG = "OculessBootReceiver"
|
||||
private var audioApps: Array<String>? = null
|
||||
private var applicationContext: Context? = null
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action
|
||||
val message = "BootDeviceReceiver onReceive, action is $action"
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
|
||||
Log.d(
|
||||
TAG,
|
||||
action!!
|
||||
)
|
||||
if (Intent.ACTION_BOOT_COMPLETED == action) {
|
||||
applicationContext = context
|
||||
startLoop()
|
||||
}
|
||||
}
|
||||
|
||||
/* Start RunAfterBootService service directly and invoke the service every 10 seconds. */
|
||||
private fun startLoop() {
|
||||
val dpm = Companion.applicationContext?.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
if (! dpm.isDeviceOwnerApp(applicationContext?.packageName!!)) {
|
||||
Log.w(TAG, "No device owner - canceling background audio thread")
|
||||
return
|
||||
}
|
||||
|
||||
updateAudioPackages()
|
||||
|
||||
val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
|
||||
scheduler.scheduleAtFixedRate(Runnable {
|
||||
enableAudioPermission()
|
||||
|
||||
}, 5, 1, TimeUnit.SECONDS)
|
||||
|
||||
val scheduler2: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
|
||||
scheduler2.scheduleAtFixedRate(Runnable {
|
||||
updateAudioPackages()
|
||||
|
||||
}, 1, 1, TimeUnit.MINUTES)
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun updateAudioPackages() {
|
||||
/* Get All Installed Packages for Audio */
|
||||
// Requires query-all-packages permission
|
||||
val packageInfoList = applicationContext?.packageManager?.getInstalledPackages(0)
|
||||
val packageNames = arrayListOf<String>()
|
||||
for (packageInfo in packageInfoList!!) {
|
||||
packageNames.add(packageInfo.packageName)
|
||||
}
|
||||
// Remove system apps
|
||||
val packageInfoListSystem = applicationContext?.packageManager?.getInstalledPackages(PackageManager.MATCH_SYSTEM_ONLY)
|
||||
for (packageInfoSystem in packageInfoListSystem!!) {
|
||||
packageNames.remove(packageInfoSystem.packageName)
|
||||
}
|
||||
// Commit to app list
|
||||
audioApps = packageNames.toTypedArray()
|
||||
}
|
||||
|
||||
private fun enableAudioPermission() {
|
||||
for (app in audioApps!!) {
|
||||
val info: ApplicationInfo ?= applicationContext?.packageManager?.getApplicationInfo(app, 0)
|
||||
// https://cs.android.com/android/platform/superproject/+/master:frameworks/proto_logging/stats/enums/app/enums.proto;l=138?q=PLAY_AUDIO
|
||||
AppOpsUtil.allowOp(applicationContext, 28, info?.uid!!, app)
|
||||
}
|
||||
}
|
||||
}
|
@ -27,9 +27,14 @@
|
||||
<string name="audio_button">Hintergrundaudio alle Apps</string>
|
||||
<string name="owner_enabled">Gerätebesitzer ist aktiviert!</string>
|
||||
<string name="owner_disabled">Informationen zu den Funktionen des Gerätebesitzers finden Sie auf Github.</string>
|
||||
<string name="audio_info">Wenn der Gerätebesitzer aktiviert ist, können alle Apps Audio im Hintergrund abspielen (ähnlich der experimentellen Einstellung, die auf einigen Geräten verfügbar ist).\nWenn Sie gerade den Gerätebesitzer aktiviert haben, halten Sie die Ein-/Aus-Taste gedrückt und starten Sie Ihr Headset neu.</string>
|
||||
<string name="audio_info_none">Wenn der Gerätebesitzer aktiviert und Service sind, können alle Apps Audio im Hintergrund abspielen (ähnlich der experimentellen Einstellung, die auf einigen Geräten verfügbar ist)</string>
|
||||
<string name="audio_info_serv">Sie müssen „Oculess“ aktivieren in den Barrierefreiheitseinstellungen.\nWenn es bereits aktiviert zu sein scheint, schalten Sie es aus und wieder ein.</string>
|
||||
<string name="audio_info_done">Aktiviert. Jetzt spielen alle Apps Audio im Hintergrund ab</string>
|
||||
<string name="disable_ownership">Entfernen Sie als Gerätebesitzer (Quest 1/2)</string>
|
||||
<string name="enable_ownership">Aktivieren Sie den Gerätebesitz</string>
|
||||
<string name="owner_info">Dies kann rückgängig gemacht werden, aber das Entfernen von Konten ist DAUERHAFT!\n1. Entfernen Sie alle Konten mit der Schaltfläche oben \n2. Mit ADB: adb shell dpm set-device-owner com.bos.oculess/.DevAdminReceiver\n(Mehr Details auf Github!)</string>
|
||||
<string name="copy">KOPIERE ES</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
|
||||
<string name="service_desc">Ermöglicht Oculess, Anwendungen Berechtigungen zum Abspielen von Audio im Hintergrund zu erteilen.</string>
|
||||
</resources>
|
@ -12,7 +12,7 @@
|
||||
|
||||
<string name="disable_companion">Disable Oculus Companion Server</string>
|
||||
<string name="enable_companion">Enable Oculus Companion Server</string>
|
||||
<string name="remove_accounts">Remove Accounts (UNSAFE)</string>
|
||||
<string name="remove_accounts">Remove/Check Accounts</string>
|
||||
<string name="disable_ota">Disable System Updates</string>
|
||||
<string name="enable_ota">Enable System Updates</string>
|
||||
<string name="telemetry">Enable/Disable Telemetry Apps</string>
|
||||
@ -20,7 +20,7 @@
|
||||
<string name="title0">Important Info</string>
|
||||
<string name="title1">Telemetry Status</string>
|
||||
<string name="message0">NOTE: Set light theme, or else text will be white on white\nPlease restart after the first time!\nRepeat this step after every restart!</string>
|
||||
<string name="message1">WARNING: Removing a Meta account is most likely irreversible and will PERMANANTLY DISABLE SOME FUNCTIONALITY!\nIt is required to remove ALL accounts if you wish to activate device admin.\n(Check GitHub for more info)</string>
|
||||
<string name="message1">WARNING: Removing a Meta account may be irreversible and can PERMANENTLY DISABLE SOME FUNCTIONALITY until factory reset.\nIt is required to remove ALL accounts if you wish to activate device admin.\n(Check GitHub for more info)</string>
|
||||
<string name="message2">Device Owner has not been set!\nPlease follow the tutorial on GitHub</string>
|
||||
<string name="message3">What would you like to do?</string>
|
||||
<string name="message4">Oculess will no longer be your device owner, and may be uninstalled normally.\nThis will disable some functions, and you will have to follow the guide if you wish to re-enable.</string>
|
||||
@ -30,9 +30,14 @@
|
||||
<string name="enable_telemetry">Enable Telemetry</string>
|
||||
<string name="disable_ownership">Remove Device Ownership</string>
|
||||
<string name="enable_ownership">Enable Device Ownership</string>
|
||||
<string name="audio_button">Background Audio for all Devices</string>
|
||||
<string name="audio_info">With device owner enabled, all apps will be allowed to play audio in the background (similar to the experimental setting available on some devices)\nIf you just activated device owner, hold the power button and restart your headset. It should be automatic after that.</string>
|
||||
<string name="audio_button">Background Audio for All</string>
|
||||
<string name="audio_info_none">With device owner and accessibility enabled, all apps will be allowed to play audio in the background (similar to the experimental setting available on some devices)</string>
|
||||
<string name="audio_info_serv">You need to enable "Oculess" in accessibility settings.\nIf it appears to be enabled already, toggle it off and on.\nClick OK to open accessibility settings.</string>
|
||||
<string name="audio_info_done">Setup finished. All apps will be allowed to play audio in the background!\nYou can disable the service in accessibility settings if you want.</string>
|
||||
<string name="owner_info">This can be undone, but REMOVING ACCOUNTS IS PERMANENT.\n1. Remove all accounts with the button above\n2. Using ADB: adb shell dpm set-device-owner com.bos.oculess/.DevAdminReceiver\n(More detail on github!)</string>
|
||||
<string name="adb" translatable="false">adb shell dpm set-device-owner com.bos.oculess/.DevAdminReceiver</string>
|
||||
<string name="copy">COPY COMMAND</string>
|
||||
<string name="settings">SETTINGS</string>
|
||||
|
||||
<string name="service_desc">Allows Oculess to give applications permissions to play audio in the background.</string>
|
||||
</resources>
|
9
app/src/main/res/xml/accessibility_service_config.xml
Normal file
9
app/src/main/res/xml/accessibility_service_config.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/service_desc"
|
||||
android:settingsActivity=""
|
||||
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
|
||||
android:accessibilityFlags="flagDefault"
|
||||
android:notificationTimeout="250"
|
||||
android:canRetrieveWindowContent="true"
|
||||
android:canRequestFilterKeyEvents="true" />
|
@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.0.1'
|
||||
classpath 'com.android.tools.build:gradle:8.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Fri May 19 12:06:25 EDT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStoreBase=GRADLE_USER_HOME
|
Loading…
Reference in New Issue
Block a user