实现带有广告支持的可访问性服务。

- 为模拟器显示设置和可访问性服务添加新的配置文件
- 实现处理Android服务和可访问性交互的类和方法
- 更新AndroidManifest以包括必要的权限和配置项
This commit is contained in:
lvlisong 2025-01-21 00:27:39 +08:00
parent 06b826cbef
commit 94b09a235f
6 changed files with 630 additions and 71 deletions

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EmulatorDisplays">
<option name="displayStateByAvdFolder">
<map>
<entry key="$USER_HOME$/.android/avd/Pixel_6_API_31.avd">
<value>
<MultiDisplayState>
<option name="displayDescriptors">
<list>
<DisplayDescriptor>
<option name="height" value="2553" />
<option name="width" value="1209" />
</DisplayDescriptor>
<DisplayDescriptor>
<option name="displayId" value="1" />
<option name="height" value="1920" />
<option name="width" value="1080" />
</DisplayDescriptor>
</list>
</option>
<option name="panelState">
<PanelState>
<option name="splitPanel">
<SplitPanelState>
<option name="proportion" value="0.9971671104431152" />
<option name="firstComponent">
<PanelState>
<option name="displayId" value="0" />
</PanelState>
</option>
<option name="secondComponent">
<PanelState>
<option name="displayId" value="1" />
</PanelState>
</option>
</SplitPanelState>
</option>
</PanelState>
</option>
</MultiDisplayState>
</value>
</entry>
</map>
</option>
</component>
</project>

362
.idea/other.xml Normal file
View File

@ -0,0 +1,362 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="direct_access_persist.xml">
<option name="deviceSelectionList">
<list>
<PersistentDeviceSelectionData>
<option name="api" value="27" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="F01L" />
<option name="id" value="F01L" />
<option name="manufacturer" value="FUJITSU" />
<option name="name" value="F-01L" />
<option name="screenDensity" value="360" />
<option name="screenX" value="720" />
<option name="screenY" value="1280" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OPPO" />
<option name="codename" value="OP573DL1" />
<option name="id" value="OP573DL1" />
<option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2557" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="28" />
<option name="brand" value="DOCOMO" />
<option name="codename" value="SH-01L" />
<option name="id" value="SH-01L" />
<option name="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="Lenovo" />
<option name="codename" value="TB370FU" />
<option name="id" value="TB370FU" />
<option name="manufacturer" value="Lenovo" />
<option name="name" value="Tab P12" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1840" />
<option name="screenY" value="2944" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="akita" />
<option name="id" value="akita" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="b0q" />
<option name="id" value="b0q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S22 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="comet" />
<option name="id" value="comet" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="29" />
<option name="brand" value="samsung" />
<option name="codename" value="crownqlteue" />
<option name="id" value="crownqlteue" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2220" />
<option name="screenY" value="1080" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="dm3q" />
<option name="id" value="dm3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S23 Ultra" />
<option name="screenDensity" value="600" />
<option name="screenX" value="1440" />
<option name="screenY" value="3088" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e1q" />
<option name="id" value="e1q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="e3q" />
<option name="id" value="e3q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24 Ultra" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1440" />
<option name="screenY" value="3120" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="eos" />
<option name="id" value="eos" />
<option name="manufacturer" value="Google" />
<option name="name" value="Eos" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="felix" />
<option name="id" value="felix" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="felix_camera" />
<option name="id" value="felix_camera" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Fold (Camera-enabled)" />
<option name="screenDensity" value="420" />
<option name="screenX" value="2208" />
<option name="screenY" value="1840" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="samsung" />
<option name="codename" value="gts8uwifi" />
<option name="id" value="gts8uwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S8 Ultra" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1848" />
<option name="screenY" value="2960" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="husky" />
<option name="id" value="husky" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8 Pro" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="motorola" />
<option name="codename" value="java" />
<option name="id" value="java" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7a" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="31" />
<option name="brand" value="google" />
<option name="codename" value="oriole" />
<option name="id" value="oriole" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="panther" />
<option name="id" value="panther" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 7" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q5q" />
<option name="id" value="q5q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold5" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1812" />
<option name="screenY" value="2176" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="q6q" />
<option name="id" value="q6q" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Z Fold6" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1856" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="r11" />
<option name="id" value="r11" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Watch" />
<option name="screenDensity" value="320" />
<option name="screenX" value="384" />
<option name="screenY" value="384" />
<option name="type" value="WEAR_OS" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 5" />
<option name="screenDensity" value="440" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="shiba" />
<option name="id" value="shiba" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 8" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2400" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="google" />
<option name="codename" value="tangorpro" />
<option name="id" value="tangorpro" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel Tablet" />
<option name="screenDensity" value="320" />
<option name="screenX" value="1600" />
<option name="screenY" value="2560" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="id" value="tokay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

View File

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<application
android:name=".BreakingNewsApplication"
android:allowBackup="true"
@ -28,6 +30,19 @@
android:name=".InterstitialActivity"
android:theme="@style/Theme.Breakingnews">
</activity>
<service
android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="false"> <!-- 明确指定 exported 属性 -->
<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>

View File

@ -1,38 +1,80 @@
package io.sixminutes.breakingnews
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.provider.Settings
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.WindowCompat
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdViewAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAdView
import io.sixminutes.breakingnews.ui.theme.BreakingnewsTheme
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity(), MaxAdViewAdListener {
class MainActivity : ComponentActivity() {
private val gaidHelper by lazy { GAIDHelper(this) }
private val TAG = "BreakingNews"
private var accessibilityService: MyAccessibilityService? = null
private lateinit var enableAccessibilityLauncher: ActivityResultLauncher<Intent>
private val ACCESSIBILITY_SERVICE_NAME = "io.sixminutes.breakingnews.MyAccessibilityService"
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
if (service is MyAccessibilityService.MyBinder) {
accessibilityService = (service as MyAccessibilityService.MyBinder).getService()
Log.d(TAG, "Accessibility service connected")
} else {
Log.e(TAG, "Invalid binder type")
}
}
override fun onServiceDisconnected(name: ComponentName?) {
accessibilityService = null
Log.d(TAG, "Accessibility service disconnected")
}
}
private fun checkAndRequestAccessibilityPermission() {
val enabledServices = Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
if (enabledServices == null ||!enabledServices.contains(ACCESSIBILITY_SERVICE_NAME)) {
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
enableAccessibilityLauncher.launch(intent)
Log.d(TAG, "Accessibility service is not enabled. Redirecting user to settings.")
} else {
Log.d(TAG, "Accessibility service is already enabled.")
continueMainActivityExecution()
}
}
private fun continueMainActivityExecution() {
// 在这里添加 MainActivity 的后续操作,例如更新 UI 或执行其他任务
Log.d(TAG, "Continuing MainActivity execution after accessibility service is enabled.")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
// 绑定服务
val intent = Intent(this, MyAccessibilityService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
setContent {
BreakingnewsTheme {
@ -41,14 +83,14 @@ class MainActivity : ComponentActivity(), MaxAdViewAdListener {
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
contentAlignment = Alignment.Center
) {
val gaid = remember { mutableStateOf<String?>(null) }
LaunchedEffect(Unit) {
gaidHelper.getAdvertisingId(object :
GAIDHelper.OnAdvertisingIdListener {
gaidHelper.getAdvertisingId(object : GAIDHelper.OnAdvertisingIdListener {
override fun onSuccess(gaidValue: String) {
gaid.value = gaidValue
Log.e(TAG, "GAID: ${gaidValue}")
Log.d(TAG, "GAID: $gaidValue")
}
override fun onFailure(e: Exception) {
@ -56,87 +98,87 @@ class MainActivity : ComponentActivity(), MaxAdViewAdListener {
}
})
}
// 使用 Column 组件进行垂直排列
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center // 垂直居中
) {
//BannerAdView(adUnitId = "119670a17d9d8ed5", listener = this@MainActivity)
GAIDInfo(gaid = gaid.value)
}
GAIDInfo(gaid = gaid.value)
}
}
}
}
enableAccessibilityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val enabledServices = Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
if (enabledServices!= null && enabledServices.contains(ACCESSIBILITY_SERVICE_NAME)) {
Log.d(TAG, "Accessibility service has been enabled.")
continueMainActivityExecution()
} else {
Log.d(TAG, "Accessibility service is still not enabled.")
}
}
}
checkAndRequestAccessibilityPermission()
// 启动 InterstitialActivity 来显示广告
showInterstitialAd()
}
private fun showInterstitialAd() {
val intent = Intent(this, InterstitialActivity::class.java)
startActivity(intent)
}
// MaxAdViewAdListener implementations
override fun onAdLoaded(ad: MaxAd) {
Log.d(TAG, "Ad loaded: ${ad.adUnitId}")
// 显示插页式广告
//InterstitialAdManager.showAd(this)
}
override fun onAdDisplayed(ad: MaxAd) {
Log.d(TAG, "Ad displayed: ${ad.adUnitId}")
override fun onDestroy() {
super.onDestroy()
// 解除服务绑定
unbindService(connection)
}
override fun onAdHidden(ad: MaxAd) {
Log.d(TAG, "Ad hidden: ${ad.adUnitId}")
}
override fun onAdClicked(ad: MaxAd) {
Log.d(TAG, "Ad clicked: ${ad.adUnitId}")
}
override fun onAdLoadFailed(ad: String, error: MaxError) {
Log.e(TAG, "Ad load failed for $ad: ${error.message}")
}
override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {
Log.e(TAG, "Ad display failed for ${ad.adUnitId}: ${error.message}")
}
override fun onAdExpanded(ad: MaxAd) {
Log.d(TAG, "Ad expanded: ${ad.adUnitId}")
}
override fun onAdCollapsed(ad: MaxAd) {
Log.d(TAG, "Ad collapsed: ${ad.adUnitId}")
// 调用点击功能的方法
fun simulateTap(x: Int, y: Int) {
accessibilityService?.simulateTap(x, y)
}
}
@Composable
fun GAIDInfo(gaid: String?) {
if (gaid != null) {
Text(text = "GAID: $gaid")
} else {
Text(text = "Loading GAID...")
}
Text(text = gaid?: "Loading GAID...")
}
@Composable
fun BannerAdView(adUnitId: String, listener: MaxAdViewAdListener) {
fun BannerAdView(
adUnitId: String,
modifier: Modifier = Modifier,
onAdLoaded: () -> Unit = {},
onAdLoadFailed: (MaxError) -> Unit = {}
) {
val context = LocalContext.current
AndroidView(
factory = { ctx ->
val adView = MaxAdView(adUnitId, ctx)
adView.setListener(listener)
adView.setListener(object : MaxAdViewAdListener {
override fun onAdLoaded(ad: MaxAd) {
onAdLoaded()
}
override fun onAdDisplayed(ad: MaxAd) {}
override fun onAdHidden(ad: MaxAd) {}
override fun onAdClicked(ad: MaxAd) {}
override fun onAdLoadFailed(adUnitId: String, error: MaxError) {
onAdLoadFailed(error)
}
override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {}
override fun onAdExpanded(ad: MaxAd) {}
override fun onAdCollapsed(ad: MaxAd) {}
})
adView.setExtraParameter("adaptive_banner", "true")
adView.setBackgroundColor(android.graphics.Color.TRANSPARENT)
adView.loadAd()
adView
},
modifier = Modifier
.fillMaxWidth() // You might not need fillMaxWidth here anymore
modifier = modifier
.fillMaxWidth()
.height(80.dp)
//.wrapContentHeight()
)
}
object InterstitialAdManager {
fun showAd(activity: ComponentActivity) {
val intent = Intent(activity, InterstitialActivity::class.java)
activity.startActivity(intent)
}
}

View File

@ -0,0 +1,85 @@
package io.sixminutes.breakingnews
import android.accessibilityservice.AccessibilityService
import android.content.Context
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import androidx.compose.ui.geometry.Rect
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
class MyAccessibilityService : AccessibilityService() {
private val TAG = "BreakingNews"
private var serviceInstance: MyAccessibilityService? = null
private val binder = MyBinder()
inner class MyBinder : Binder() {
fun getService(): MyAccessibilityService? {
Log.d(TAG, "Binder getService called")
return serviceInstance
}
}
override fun onServiceConnected() {
super.onServiceConnected()
serviceInstance = this
Log.d(TAG, "Service connected")
}
override fun onInterrupt() {
Log.d(TAG, "Service interrupted")
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// 处理无障碍事件
}
override fun onUnbind(intent: Intent?): Boolean {
serviceInstance = null
return super.onUnbind(intent)
}
companion object {
private var instance: MyAccessibilityService? = null
fun getInstance(): MyAccessibilityService? {
return instance
}
}
fun simulateTap(x: Int, y: Int) {
val rootNode = AccessibilityNodeInfoCompat.wrap(rootInActiveWindow)
if (rootNode!= null) {
val clickableNodes = ArrayList<AccessibilityNodeInfoCompat>()
findClickableNodes(rootNode, clickableNodes)
for (node in clickableNodes) {
val bounds = android.graphics.Rect()
node.getBoundsInScreen(bounds)
if (bounds.contains(x, y)) {
node.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK)
Log.d(TAG, "Clicked node at ($x,$y)")
break
}
}
} else {
Log.e(TAG, "No root node found")
}
}
private fun findClickableNodes(node: AccessibilityNodeInfoCompat, clickableNodes: ArrayList<AccessibilityNodeInfoCompat>) {
if (node.isClickable) {
clickableNodes.add(node)
}
val childCount = node.childCount
for (i in 0 until childCount) {
val child = node.getChild(i)
if (child!= null) {
findClickableNodes(child, clickableNodes)
child.recycle()
}
}
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:canPerformGestures="true"
/>