目标API 34(Android 14)

This commit is contained in:
AceDroidX 2024-04-01 15:22:02 +08:00
parent b985523034
commit b02ed4f508
9 changed files with 74 additions and 34 deletions

View File

@ -8,6 +8,10 @@ def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android { android {
buildFeatures {
buildConfig = true
}
signingConfigs { signingConfigs {
AceKeystore { AceKeystore {
keyAlias keystoreProperties['keyAlias'] keyAlias keystoreProperties['keyAlias']
@ -16,15 +20,14 @@ android {
storePassword keystoreProperties['storePassword'] storePassword keystoreProperties['storePassword']
} }
} }
compileSdkVersion 32
buildToolsVersion "33.0.0-rc4"
defaultConfig { defaultConfig {
applicationId "io.github.acedroidx.frp" applicationId "io.github.acedroidx.frp"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 32 targetSdkVersion 34
versionCode 3 compileSdk 34
versionName "1.0.2" versionCode 4
versionName "1.0.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -42,11 +45,11 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_11 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = '11' jvmTarget = '17'
} }
packagingOptions { packagingOptions {
jniLibs { jniLibs {
@ -57,7 +60,7 @@ android {
abi { abi {
enable true enable true
reset() reset()
include "arm64-v8a", "x86_64" include "arm64-v8a", "x86_64", "armeabi-v7a"
universalApk true universalApk true
} }
} }
@ -66,11 +69,11 @@ android {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.6.0' implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
} }

View File

@ -6,6 +6,8 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@ -24,7 +26,12 @@
<service <service
android:name=".ShellService" android:name=".ShellService"
android:enabled="true" android:enabled="true"
android:exported="false" /> android:exported="false"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="explanation_for_special_use" />
</service>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@ -1,5 +1,6 @@
package io.github.acedroidx.frp package io.github.acedroidx.frp
import android.Manifest
import android.app.ActivityManager import android.app.ActivityManager
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
@ -7,20 +8,23 @@ import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat
import java.io.File import java.io.File
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
val filename = "libfrpc.so" val filename = "libfrpc.so"
val frpver = "0.42.0" val frpver = "0.56.0"
val logname = "frpc.log" val logname = "frpc.log"
val configname = "config.ini" val configname = "config.ini"
@ -57,6 +61,7 @@ class MainActivity : AppCompatActivity() {
titleText.text = "frp for Android - ${versionName}/${frpver}" titleText.text = "frp for Android - ${versionName}/${frpver}"
checkConfig() checkConfig()
checkNotificationPermission()
createBGNotificationChannel() createBGNotificationChannel()
mBound = isServiceRunning(ShellService::class.java) mBound = isServiceRunning(ShellService::class.java)
@ -145,6 +150,31 @@ class MainActivity : AppCompatActivity() {
stopService(intent) stopService(intent)
} }
private fun checkNotificationPermission() {
val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// Permission is granted. Continue the action or workflow in your
// app.
} else {
// Explain to the user that the feature is unavailable because the
// feature requires a permission that the user has denied. At the
// same time, respect the user's decision. Don't link to system
// settings in an effort to convince the user to change their
// decision.
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}
private fun createBGNotificationChannel() { private fun createBGNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because // Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library // the NotificationChannel class is new and not in the support library

View File

@ -6,6 +6,7 @@ import android.app.Service
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Binder import android.os.Binder
import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
@ -60,11 +61,8 @@ class ShellService : Service() {
packageManager.getApplicationInfo(packageName, PackageManager.GET_SHARED_LIBRARY_FILES) packageManager.getApplicationInfo(packageName, PackageManager.GET_SHARED_LIBRARY_FILES)
Log.d("adx", "native library dir ${ainfo.nativeLibraryDir}") Log.d("adx", "native library dir ${ainfo.nativeLibraryDir}")
try { try {
p = Runtime.getRuntime() p = Runtime.getRuntime().exec(
.exec( "${ainfo.nativeLibraryDir}/${filename} -c config.ini", arrayOf(""), this.filesDir
"${ainfo.nativeLibraryDir}/${filename} -c config.ini",
arrayOf(""),
this.filesDir
) )
} catch (e: Exception) { } catch (e: Exception) {
Log.e("adx", e.stackTraceToString()) Log.e("adx", e.stackTraceToString())
@ -88,13 +86,16 @@ class ShellService : Service() {
Intent(this, MainActivity::class.java).let { notificationIntent -> Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE) PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
} }
val notification: Notification = NotificationCompat.Builder(this, "shell_bg") val notification = NotificationCompat.Builder(this, "shell_bg")
.setSmallIcon(R.drawable.ic_launcher_foreground) .setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle("frp后台服务")
.setContentTitle("frp后台服务")
.setContentText("已启动frp") .setContentText("已启动frp")
//.setTicker("test") //.setTicker("test")
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
return notification.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
.build() .build()
return notification } else {
return notification.build()
}
} }
} }

Binary file not shown.

View File

@ -1,9 +1,9 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = "1.6.21" ext.kotlin_version = "1.9.20"
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.3.1' classpath 'com.android.tools.build:gradle:8.3.1'
@ -17,10 +17,10 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
} }
task clean(type: Delete) { tasks.register('clean', Delete) {
delete rootProject.buildDir delete rootProject.layout.buildDirectory
} }

View File

@ -19,6 +19,5 @@ android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete": # Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false android.nonTransitiveRClass=false
android.nonFinalResIds=false android.nonFinalResIds=false