diff --git a/.idea/emulatorDisplays.xml b/.idea/emulatorDisplays.xml
new file mode 100644
index 0000000..e6b4ce5
--- /dev/null
+++ b/.idea/emulatorDisplays.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/other.xml b/.idea/other.xml
new file mode 100644
index 0000000..e3e6e5d
--- /dev/null
+++ b/.idea/other.xml
@@ -0,0 +1,362 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 157e591..12a52e6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/app/src/main/java/io/sixminutes/breakingnews/MainActivity.kt b/app/src/main/java/io/sixminutes/breakingnews/MainActivity.kt
index 5091edd..4d21b4f 100644
--- a/app/src/main/java/io/sixminutes/breakingnews/MainActivity.kt
+++ b/app/src/main/java/io/sixminutes/breakingnews/MainActivity.kt
@@ -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
+ 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(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()
)
-}
\ No newline at end of file
+}
+
+object InterstitialAdManager {
+ fun showAd(activity: ComponentActivity) {
+ val intent = Intent(activity, InterstitialActivity::class.java)
+ activity.startActivity(intent)
+ }
+}
diff --git a/app/src/main/java/io/sixminutes/breakingnews/MyAccessibiltyService.kt b/app/src/main/java/io/sixminutes/breakingnews/MyAccessibiltyService.kt
new file mode 100644
index 0000000..145afc1
--- /dev/null
+++ b/app/src/main/java/io/sixminutes/breakingnews/MyAccessibiltyService.kt
@@ -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()
+ 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) {
+ 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()
+ }
+ }
+ }
+}
diff --git a/app/src/main/res/xml/accessibility_service_config.xml b/app/src/main/res/xml/accessibility_service_config.xml
new file mode 100644
index 0000000..1658387
--- /dev/null
+++ b/app/src/main/res/xml/accessibility_service_config.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file