Commit 2e61c3b6 authored by wanglei's avatar wanglei

...

parent e699a845
*.iml
.gradle
/local.properties
.idea
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/build
\ No newline at end of file
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.base.localweatherwhite"
compileSdk = 34
defaultConfig {
applicationId = "com.base.localweatherwhite"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
viewBinding = true
buildConfig = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
// 语种切换框架:https://github.com/getActivity/MultiLanguages
implementation("com.github.getActivity:MultiLanguages:9.3")
// 沉浸式状态栏,基础依赖包,必须要依赖
api (libs.immersionbar)
// 沉浸式状态栏kotlin扩展(可选)
api (libs.immersionbar.ktx)
//solar 归因
implementation("com.reyun.solar.engine.oversea:solar-engine-core:1.2.8.3")
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.base.appzxhy
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.base.localweatherwhite", appContext.packageName)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LocalWeatherWhite"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
package com.base.appzxhy
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.databinding.ActivityMainBinding
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
}
\ No newline at end of file
package com.base.appzxhy
import android.app.Activity
import android.app.Application
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import com.base.appzxhy.bean.ConstObject.appLanguageCountrySp
import com.base.appzxhy.bean.ConstObject.appLanguageSp
import com.base.appzxhy.helper.AppConfig
import com.base.appzxhy.utils.ActivityManagerUtils
import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.LogEx
import com.hjq.language.MultiLanguages
import com.hjq.language.OnLanguageListener
import java.util.Locale
import java.util.UUID
class MyApplication : Application() {
private val TAG = "MyApplication"
var uuid = ""
companion object {
lateinit var appContext: MyApplication
@JvmField
var PAUSED_VALUE = 0
}
override fun onCreate() {
super.onCreate()
appContext = this
initUUid()
initApp()
// 初始化语种切换框架
MultiLanguages.init(this)
// 设置语种变化监听器
MultiLanguages.setOnLanguageListener(object : OnLanguageListener {
override fun onAppLocaleChange(oldLocale: Locale, newLocale: Locale) {
appLanguageSp = newLocale.language
appLanguageCountrySp = newLocale.country
Log.i("MultiLanguages", "监听到应用切换了语种,旧语种:$oldLocale,新语种:$newLocale")
}
override fun onSystemLocaleChange(oldLocale: Locale, newLocale: Locale) {
Log.i(
"MultiLanguages", "监听到系统切换了语种,旧语种:" + oldLocale + ",新语种:" + newLocale +
",是否跟随系统:" + MultiLanguages.isSystemLanguage(this@MyApplication)
)
}
})
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(MultiLanguages.attach(base))
}
private fun initUUid() {
uuid = AppPreferences.getInstance().getString("uuid", "")
if (TextUtils.isEmpty(uuid)) {
uuid = UUID.randomUUID().toString() + System.currentTimeMillis()
AppPreferences.getInstance().put("uuid", uuid)
LogEx.logDebug(TAG, "uuid=$uuid")
}
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
}
private fun initApp() {
//初始化广告相关业务
// AdsMgr.init(appContext)
// FacebookSdk.sdkInitialize(applicationContext)
// val token = AppPreferences.getInstance().getString("token", "")
// val topic = AppConfig.packageName + "_push"
// LogEx.logDebug(TAG, "topic=${topic} token=$token")
// FCMManager.initFirebase(this)
// FCMManager.subscribeToTopic(topic)
// initConfig()
//
// Thread {
// InstallHelps.init {
// initRemoteConfig()
// }
// }.start()
// SolarEngineManager.getInstance().preInit(this, solarkey)
initLifeListener()
// ScreenStatusReceiver.registerScreenStatusReceiver(this)
// PackageStatusReceiver.registerPackageStatusReceiver(this)
// BatteryStatusReceiver.registerBatteryStatusReceiver(this)
// startJob()
// startAlarm(appContext, 24)
// startAlarm(appContext, 48)
// startAlarm(appContext, 72)
}
private var lastTimePause = 0L
private var lastTimeResume = 0L
private fun isHotLaunch(): Boolean {
if ((lastTimeResume - lastTimePause) > 5000) {
return true
}
return false
}
private fun initLifeListener() {
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
private var count = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
ActivityManagerUtils.getInstance().addActivity(activity)
}
override fun onActivityStarted(activity: Activity) {
count++
lastTimeResume = System.currentTimeMillis()
if (count == 1 && isHotLaunch()) {
val topActivity: Activity? = ActivityManagerUtils.getInstance().topActivity
val flag = if (topActivity == null) {
true
} else {
AppConfig.noLoadingActivities.all { !topActivity.localClassName.contains(it, true) }
}
LogEx.logDebug(TAG, "flag=$flag" + " activity:" + activity.localClassName)
if (flag) {
// topActivity?.startActivity(
// Intent(
// topActivity, SplashActivity::class.java
// ).apply {
// putExtra("isHotLaunch", true)
// putExtra("type", -1)
// })
}
}
lastTimeResume = 0
}
override fun onActivityResumed(activity: Activity) {
PAUSED_VALUE = 1
}
override fun onActivityPaused(activity: Activity) {
PAUSED_VALUE = 2
lastTimePause = System.currentTimeMillis()
}
override fun onActivityStopped(activity: Activity) {
count--
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
ActivityManagerUtils.getInstance().removeActivity(activity)
}
})
}
private fun initRemoteConfig() {
// NewComUtils.requestCfg { config ->
// if (config != null) {
// AppPreferences.getInstance().put("config", config)
// }
//
// LogEx.logDebug("requestCfg", "config=$config")
//
// initConfig(config)
// }
}
private fun initConfig(config: String? = AppPreferences.getInstance().getString("config", "")) {
// kotlin.runCatching {
// val configBean = Gson().fromJson(config, ConfigBean::class.java)
//
// val jsonObject = JSONObject()
// jsonObject.put("ut", configBean.ut)
// EventUtils.event("user_type", ext = jsonObject)
//
// //配置
// ConfigBean.configBean = configBean
//
// //广告
// AdsMgr.adsConfigBean = configBean.adConfigBean
// com.base.localweatherwhite.utils.LogEx.logDebug("initConfig", "AdsMgr.adsConfigBean=${configBean.adConfigBean.functionInShowAd}")
//
// //通知
// PopupConstObject.popupConfigBean = configBean.popupConfigBean
//
// //启动定时器
// changeTimer()
// }
}
}
\ No newline at end of file
package com.base.appzxhy.base
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.base.appzxhy.MainActivity
import com.base.appzxhy.R
import com.base.appzxhy.bean.ConstObject.appLanguageCountrySp
import com.base.appzxhy.bean.ConstObject.appLanguageSp
import com.base.appzxhy.helper.EventUtils
import com.base.appzxhy.utils.ActivityLauncher
import com.base.appzxhy.utils.ActivityManagerUtils
import com.base.appzxhy.utils.LogEx
import com.gyf.immersionbar.ktx.immersionBar
import com.hjq.language.MultiLanguages
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.Locale
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.random.Random
abstract class BaseActivity<VB : ViewBinding>(
bindingInflater: (LayoutInflater) -> VB
) : AppCompatActivity() {
open val TAG = javaClass.simpleName
private val tagNo = Random.nextInt(500)
val binding by lazy(LazyThreadSafetyMode.NONE) {
bindingInflater(layoutInflater)
}
lateinit var launcher: ActivityLauncher
private var currentLocale: Locale? = null
var onCreateI = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onCreateI++
LogEx.logDebug(TAG, "lifecycle $tagNo onCreate ${javaClass.simpleName} $onCreateI")
launcher = ActivityLauncher(this)
setContentView(binding.root)
EventUtils.event("page_${javaClass.simpleName}")
currentLocale = Locale(appLanguageSp, appLanguageCountrySp)
initView()
initListener()
}
protected open fun initView() {}
protected open fun initListener() {}
fun finishToMain(delay: Long = 0) {
val flag = this !is MainActivity && !ActivityManagerUtils.getInstance().isActivityInStack(MainActivity::class.java)
if (flag) {
startActivity(Intent(this, MainActivity::class.java).apply {
putExtra("where", "finishToMain")
})
}
lifecycleScope.launch(Dispatchers.Main) {
delay(delay)
finish()
}
}
fun finishToMainTop() {
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("where", "finishToMainTop")
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
startActivity(intent)
}
var dialog: Dialog? = null
override fun onDestroy() {
super.onDestroy()
ActivityManagerUtils.getInstance().removeActivity(this)
if (dialog != null) {
dialog?.dismiss()
dialog = null
}
}
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(MultiLanguages.attach(newBase))
}
fun changeLanguage(currentActivity: Activity, bundle: Bundle = Bundle()): Boolean {
val spLanguage = Locale(appLanguageSp, appLanguageCountrySp)
val flag = currentLocale != spLanguage
val restart = MultiLanguages.setAppLanguage(this, spLanguage)
LogEx.logDebug(
TAG, "changeLanguage " +
"flag=$flag restart=$restart currentLocale=$currentLocale spLanguage=$spLanguage"
)
if (restart) {
currentLocale = Locale(appLanguageSp, appLanguageCountrySp)
}
if (flag || restart) {
// 1.使用 recreate 来重启 Activity,效果差,有闪屏的缺陷
// recreate();
// 2.使用常规 startActivity 来重启 Activity,有从左向右的切换动画
// 稍微比 recreate 的效果好一点,但是这种并不是最佳的效果
// startActivity(new Intent(this, LanguageActivity.class));
// finish();
// 3.我们可以充分运用 Activity 跳转动画,在跳转的时候设置一个渐变的效果,相比前面的两种带来的体验是最佳的
//需要设置启动模式,避免AndroidManifest.xml设置singleTop启动模式导致重复启动不生效
//这种方式如果设置了singleTop或者singleTask的,再次回到该activity无法改变于语言,因为还在堆栈里没有重新创建
needRecreate()
if (needRecreate()) {
LogEx.logDebug(TAG, "changeLanguage recreate")
recreate()
} else {
startActivity(Intent(this, currentActivity::class.java).apply {
putExtras(bundle)
})
overridePendingTransition(R.anim.activity_alpha_in, R.anim.activity_alpha_out)
finish()
}
return true
}
return false
}
/**
* 判断是否需要重新创建对SingleTop启动模式的有效
*/
fun needRecreate(): Boolean {
return TAG.contains("MainActivity")
}
/**
* 避免在onResume--onPause周期内,多次调用
* 在onStop中重置标志
*/
private val onResumeCalled = AtomicBoolean(false)
private var onResumeOneShootI = 0
open fun onResumeOneShoot() {
onResumeOneShootI++
LogEx.logDebug(TAG, "lifecycle $tagNo onResumeOneShoot ${javaClass.simpleName} $onResumeOneShootI")
}
private var onResumeI = 0
override fun onResume() {
super.onResume()
onResumeI++
LogEx.logDebug(TAG, "lifecycle $tagNo onResume ${javaClass.simpleName} $onResumeI")
if (!onResumeCalled.get()) {
onResumeCalled.set(true)
onResumeOneShoot()
}
}
private var onStartI = 0
override fun onStart() {
super.onStart()
onStartI++
LogEx.logDebug(TAG, "lifecycle $tagNo onStart ${javaClass.simpleName} $onStartI")
}
private var onStopI = 0
override fun onStop() {
super.onStop()
onStopI++
LogEx.logDebug(TAG, "lifecycle $tagNo onStop ${javaClass.simpleName} $onStopI")
onResumeCalled.set(false)
}
private var onPauseI = 0
override fun onPause() {
super.onPause()
onPauseI++
LogEx.logDebug(TAG, "lifecycle $tagNo onPause ${javaClass.simpleName} $onPauseI")
}
open fun configSystemBar() {
immersionBar {
statusBarColor("#FFFFFFFF")
navigationBarColor("#FFFFFFFF")
statusBarDarkFont(true)
navigationBarDarkIcon(true)
fitsSystemWindows(true)
}
}
}
\ No newline at end of file
package com.base.appzxhy.bean
import com.base.appzxhy.utils.AppPreferences
import java.util.Locale
object ConstObject {
var isFirstLauncher = true
get() {
return AppPreferences.getInstance().getBoolean("isFirstLauncher", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("isFirstLauncher", value, true)
}
var appLanguageSp = Locale.getDefault().language
get() {
return AppPreferences.getInstance().getString("languageSp", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("languageSp", value, true)
}
var appLanguageCountrySp = Locale.getDefault().country
get() {
return AppPreferences.getInstance().getString("languageCountrySp", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("languageCountrySp", value, true)
}
var noShowFriendsShareGuide = false
get() {
return AppPreferences.getInstance().getBoolean("noShowFriendsShareGuide", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("noShowFriendsShareGuide", value, true)
}
}
\ No newline at end of file
package com.base.appzxhy.helper
import android.util.Base64
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
object AESHelper {
private const val aesKey = "7vwdrlk6bp8rihe4"
private val cipher by lazy {
Cipher.getInstance("AES/GCM/NoPadding")
}
fun encrypt(content: String): String {
try {
val iv = ByteArray(12).apply {
SecureRandom().nextBytes(this)
}
val contentBytes = content.toByteArray(Charsets.UTF_8)
val params = GCMParameterSpec(128, iv)
cipher.init(
Cipher.ENCRYPT_MODE,
secretKey, params
)
val encryptData = cipher.doFinal(contentBytes)
if (encryptData.size != contentBytes.size + 16) {
throw IllegalStateException("Encryption failed")
}
val message = ByteArray(12 + contentBytes.size + 16)
System.arraycopy(iv, 0, message, 0, 12)
System.arraycopy(encryptData, 0, message, 12, encryptData.size)
return String(Base64.encode(message, Base64.NO_WRAP), Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
@Synchronized
fun decrypt(content: String): String {
try {
val con = content.replace(" ".toRegex(), "+")
val contentByte = Base64.decode(con, Base64.NO_WRAP)
require(contentByte.size >= 12 + 16)
val params = GCMParameterSpec(128, contentByte, 0, 12)
cipher.init(
Cipher.DECRYPT_MODE,
secretKey, params
)
val decryptData = cipher.doFinal(contentByte, 12, contentByte.size - 12)
return String(decryptData, Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
private val secretKey by lazy {
SecretKeySpec(aesKey.toByteArray(), "AES")
}
}
\ No newline at end of file
package com.base.appzxhy.helper
object AppConfig {
const val privacyPolicy: String = ""
const val termService: String = ""
// 正式包名
const val packageName = "com.loactation.alibabab.ccccaa"
// 域名
const val eventUrl = "https://rp.gamexzonerk.xyz"
const val apiUrl = "https://api.gamexzonerk.xyz"
val noLoadingActivities = listOf(
"full", // 过滤全屏广告
"adActivity",
"AdActivity",
"AppLovinFullscreenActivity",
// SplashActivity::class.java.simpleName,
// 返回前台时不跳转启动页的 activity
)
}
\ No newline at end of file
package com.base.appzxhy.helper
import android.os.Build
import com.base.appzxhy.BuildConfig
import com.base.appzxhy.helper.ReportUtils.doPost
import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.LogEx
import org.json.JSONException
import org.json.JSONObject
import java.util.TimeZone
object EventUtils {
private val TAG = "EventUtils"
var ifAgreePrivacy = true
get() {
return AppPreferences.getInstance().getBoolean("ifAgreePrivacy", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("ifAgreePrivacy", value, true)
}
fun event(
key: String,
value: String? = null,
ext: JSONObject? = null,
) {
if (!ifAgreePrivacy) {
return
}
Thread {
var paramJson: String? = ""
try {
val pkg = AppConfig.packageName
val s = JSONObject()
.put("action", key)
.put("value", value)
.put("ext", ext)
val s2 = JSONObject()
.put("${pkg}_3", AppPreferences.getInstance().getString("Equipment", ""))
.put("${pkg}_4", AppPreferences.getInstance().getString("Manufacturer", ""))
.put("${pkg}_5", Build.VERSION.SDK_INT)
.put("${pkg}_9", AppPreferences.getInstance().getString("uuid", ""))
.put("${pkg}_10", AppPreferences.getInstance().getString("gid", ""))
.put("${pkg}_13", "android")
.put("${pkg}_15", "google")
.put("${pkg}_14", BuildConfig.VERSION_CODE)
.put("${pkg}_8", BuildConfig.VERSION_NAME)
.put("${pkg}_24", BuildConfig.BUILD_TYPE)
.put("${pkg}_34", TimeZone.getDefault().getID())
val data = JSONObject()
.put("data", s)
.put("bp", s2)
.toString()
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
LogEx.logDebug(TAG, "gid=${AppPreferences.getInstance().getString("gid", "")}")
paramJson = AESHelper.encrypt(data)
} catch (e: JSONException) {
paramJson = ""
}
LogEx.logDebug(TAG, "url=$url")
doPost(
url,
HashMap(),
paramJson
)
}.start()
}
private val url by lazy {
val pkg = AppConfig.packageName
val url = StringBuilder(
"${AppConfig.eventUrl}/${
pkg.filter { it.isLowerCase() }.substring(4, 9)
}sp"
)
url.append("?pkg=$pkg")
url.toString()
}
}
\ No newline at end of file
package com.base.appzxhy.helper;
import android.text.TextUtils;
import com.base.appzxhy.utils.LogEx;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
public class ReportUtils {
private static String TAG = "ReportUtils";
public static String doPost(String urlPath, Map<String, String> paramsMap, String json) {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(urlPath).openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
if (!TextUtils.isEmpty(json)) {
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Content-Length", Integer.toString(json.getBytes().length));
conn.getOutputStream().write(json.getBytes());
}
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
result.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
if (result.length() > 0) {
try {
conn.getOutputStream().write(result.substring(1).getBytes());
} catch (Exception e) {
}
} else {
// conn.getOutputStream().write(result.substring(0).getBytes());
}
if (conn.getResponseCode() == 200) {
String s = new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine();
if (!TextUtils.isEmpty(s)) {
} else {
s = "";
}
LogEx.INSTANCE.logDebug(TAG, "code=200", false);
return s;
} else {
LogEx.INSTANCE.logDebug(TAG, "code!=200", false);
}
} catch (Exception e) {
e.printStackTrace();
}
return "{ \"success\": false,\n \"errorMsg\": \"后台服务器开小差了!\",\n \"result\":{}}";
}
}
package com.base.appzxhy.utils
import android.content.Intent
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultCaller
import androidx.activity.result.contract.ActivityResultContracts
class ActivityLauncher(activityResultCaller: ActivityResultCaller) {
//region 权限
private var permissionCallback: ActivityResultCallback<Map<String, Boolean>>? = null
private val permissionLauncher =
activityResultCaller.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: Map<String, Boolean> ->
permissionCallback?.onActivityResult(result)
}
fun launch(
permissionArray: Array<String>,
permissionCallback: ActivityResultCallback<Map<String, Boolean>>?
) {
this.permissionCallback = permissionCallback
permissionLauncher.launch(permissionArray)
}
//endregion
//region intent跳转
private var activityResultCallback: ActivityResultCallback<ActivityResult>? = null
private val intentLauncher =
activityResultCaller.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult: ActivityResult ->
activityResultCallback?.onActivityResult(activityResult)
}
/**
* it.resultCode == Activity.RESULT_OK
*/
fun launch(
intent: Intent,
activityResultCallback: ActivityResultCallback<ActivityResult>? = null
) {
this.activityResultCallback = activityResultCallback
intentLauncher.launch(intent)
}
//endregion
//region saf
// private var safResultCallback: ActivityResultCallback<Uri?>? = null
// private val safLauncher =
// activityResultCaller.registerForActivityResult(
// ActivityResultContracts.OpenDocument(),
// ) { uri ->
// safResultCallback?.onActivityResult(uri)
// }
//
// fun launch(array: Array<String>, safResultCallback: ActivityResultCallback<Uri?>?) {
// this.safResultCallback = safResultCallback
// safLauncher.launch(array)
// }
//end region
}
\ No newline at end of file
package com.base.appzxhy.utils;
import android.app.Activity;
import java.util.Stack;
public class ActivityManagerUtils {
private static ActivityManagerUtils instance;
private Stack<Activity> activityStack = new Stack<>();
private ActivityManagerUtils() {
}
public static ActivityManagerUtils getInstance() {
if (instance == null) {
instance = new ActivityManagerUtils();
}
return instance;
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
activityStack.add(activity);
}
/**
* 移除Activity从堆栈
*/
public void removeActivity(Activity activity) {
activityStack.remove(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity getCurrentActivity() {
return activityStack.lastElement();
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (Activity activity : activityStack) {
if (activity != null) {
activity.finish();
}
}
activityStack.clear();
}
/**
* 检查Activity是否存在于堆栈中
*/
public boolean isActivityInStack(Class<?> cls) {
boolean isExist = false;
if (cls != null) {
for (Activity activity : activityStack) {
if (cls.equals(activity.getClass())) {
isExist = true;
break;
}
}
}
return isExist;
}
public Activity getTopActivity() {
if (activityStack.empty()) {
return null;
} else {
return activityStack.peek();
}
}
}
\ No newline at end of file
package com.base.appzxhy.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import com.base.appzxhy.MyApplication;
import java.util.Set;
/**
* @noinspection ALL, rawtypes, rawtypes
*/
public class AppPreferences {
private static AppPreferences sInstance;
private final SharedPreferences sharedPreferences;
private static final String PREF_FILE_NAME = "app_prefs"; // 偏好文件名
private AppPreferences(Context context) {
sharedPreferences = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE);
}
public static synchronized AppPreferences getInstance() {
if (sInstance == null) {
sInstance = new AppPreferences(MyApplication.appContext.getApplicationContext());
}
return sInstance;
}
// 通用 put 方法
public void put(String key, Object value) {
if (value instanceof Integer) {
sharedPreferences.edit().putInt(key, (Integer) value).apply();
} else if (value instanceof Long) {
sharedPreferences.edit().putLong(key, (Long) value).apply();
} else if (value instanceof Float) {
sharedPreferences.edit().putFloat(key, (Float) value).apply();
} else if (value instanceof Boolean) {
sharedPreferences.edit().putBoolean(key, (Boolean) value).apply();
} else if (value instanceof String) {
sharedPreferences.edit().putString(key, (String) value).apply();
} else if (value instanceof Double) {
sharedPreferences.edit().putString(key, (String) value.toString()).apply();
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
}
@SuppressLint("ApplySharedPref")
public void put(String key, Object value, boolean isCommit) {
SharedPreferences.Editor editor = sharedPreferences.edit();
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof Long) {
editor.putLong(key, (Long) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
} else if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
// 根据 isCommit 参数的值决定使用 commit() 还是 apply()
if (isCommit) {
editor.commit();
} else {
editor.apply();
}
}
// 存入整数
public void putInt(String key, int value) {
sharedPreferences.edit().putInt(key, value).apply();
}
public void putStringSet(String key, Set value) {
sharedPreferences.edit().putStringSet(key, value).apply();
}
public Set<String> getStringSet(String key, Set<String> defaultValue) {
return sharedPreferences.getStringSet(key, defaultValue);
}
// 获取整数
public int getInt(String key, int defaultValue) {
return sharedPreferences.getInt(key, defaultValue);
}
// 存入长整数
public void putLong(String key, long value) {
sharedPreferences.edit().putLong(key, value).apply();
}
// 获取长整数
public long getLong(String key, long defaultValue) {
return sharedPreferences.getLong(key, defaultValue);
}
// 存入浮点数
public void putFloat(String key, float value) {
sharedPreferences.edit().putFloat(key, value).apply();
}
// 获取浮点数
public float getFloat(String key, float defaultValue) {
return sharedPreferences.getFloat(key, defaultValue);
}
// 存入布尔值
public void putBoolean(String key, boolean value) {
sharedPreferences.edit().putBoolean(key, value).apply();
}
// 获取布尔值
public boolean getBoolean(String key, boolean defaultValue) {
return sharedPreferences.getBoolean(key, defaultValue);
}
// 存入字符串
public void putString(String key, String value) {
sharedPreferences.edit().putString(key, value).apply();
}
// 获取字符串
public String getString(String key, String defaultValue) {
return sharedPreferences.getString(key, defaultValue);
}
// 检查某个键是否存在
public boolean contains(String key) {
return sharedPreferences.contains(key);
}
// 移除某个键
public void remove(String key) {
sharedPreferences.edit().remove(key).apply();
}
// 清除所有数据
public void clear() {
sharedPreferences.edit().clear().apply();
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.annotation.ColorInt
@SuppressLint("ObsoleteSdkInt")
object BarUtils {
fun setStatusBarLightMode(activity: Activity, isLightMode: Boolean) {
setStatusBarLightMode(activity.window, isLightMode)
}
private fun setStatusBarLightMode(window: Window, isLightMode: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val decorView = window.decorView
var vis = decorView.systemUiVisibility
vis = if (isLightMode) {
vis or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
vis and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
decorView.systemUiVisibility = vis
}
}
fun setStatusBarColor(activity: Activity, @ColorInt color: Int): View? {
return setStatusBarColor(activity, color, false)
}
private fun setStatusBarColor(activity: Activity, @ColorInt color: Int, isDecor: Boolean): View? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null
transparentStatusBar(activity)
return applyStatusBarColor(activity, color, isDecor)
}
private fun applyStatusBarColor(activity: Activity, color: Int, isDecor: Boolean): View {
return applyStatusBarColor(activity.window, color, isDecor)
}
private fun transparentStatusBar(activity: Activity) {
transparentStatusBar(activity.window)
}
private fun transparentStatusBar(window: Window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
val option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
val vis = window.decorView.systemUiVisibility
window.decorView.systemUiVisibility = option or vis
window.statusBarColor = Color.TRANSPARENT
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
}
private fun applyStatusBarColor(window: Window, color: Int, isDecor: Boolean): View {
val parent =
if (isDecor) window.decorView as ViewGroup else (window.findViewById<View>(android.R.id.content) as ViewGroup)!!
var fakeStatusBarView =
parent.findViewWithTag<View>(TAG_STATUS_BAR)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(color)
} else {
fakeStatusBarView = createStatusBarView(window.context, color)
parent.addView(fakeStatusBarView)
}
return fakeStatusBarView
}
private fun createStatusBarView(context: Context, color: Int): View {
val statusBarView = View(context)
statusBarView.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()
)
statusBarView.setBackgroundColor(color)
statusBarView.tag = TAG_STATUS_BAR
return statusBarView
}
///////////////////////////////////////////////////////////////////////////
// status bar
///////////////////////////////////////////////////////////////////////////
private const val TAG_STATUS_BAR = "TAG_STATUS_BAR"
@SuppressLint("DiscouragedApi", "InternalInsetResource")
fun getStatusBarHeight(): Int {
val resources = Resources.getSystem()
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
object BatteryUtils {
fun Context.getBatteryLevel(): Int {
val batteryLevel: Int
val intent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
return when {
intent != null -> {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
batteryLevel = if (scale != -1) {
(level * 100 / scale).toInt()
} else {
-1
}
batteryLevel
}
else -> -1 // 无法获取电量信息
}
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
object ClipboardUtils {
fun Context.copyText(label: String, text: String) {
val clipboard: ClipboardManager = getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
// 创建一个ClipData对象,其中包含要复制的文本
// val clip = ClipData.newPlainText("uuid", "uuid=$uuid gid=$gid")
val clip = ClipData.newPlainText(label, text)
// 将ClipData对象设置到剪贴板中
clipboard.setPrimaryClip(clip)
}
}
\ No newline at end of file
package com.base.appzxhy.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.base.appzxhy.MyApplication;
/**
* 做尺寸转换的工具类。在dp/sp/px之间自由转换
*
* @noinspection unused
*/
public class DensityUtils {
@SuppressLint("StaticFieldLeak")
static Context context = MyApplication.appContext;
public static int dip2px(float dipValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public static int dip2px(float dipValue, float toScale) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) ((dipValue * scale + 0.5f) * toScale);
}
public static int px2dip(float pxValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int px2sp(float pxValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int sp2px(float spValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (spValue * scale + 0.5f);
}
public static int getWidth() {
initScreen();
if (screen != null) {
return screen.widthPixels;
}
return 0;
}
public static int getHeight() {
initScreen();
if (screen != null) {
return screen.heightPixels;
}
return 0;
}
/**
* @noinspection SuspiciousNameCombination
*/
static void initScreen() {
if (screen == null) {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
if (dm.widthPixels > dm.heightPixels) {
screen = new Screen(dm.heightPixels, dm.widthPixels);
} else {
screen = new Screen(dm.widthPixels, dm.heightPixels);
}
}
}
static Screen screen = null;
public static class Screen {
public int widthPixels;
public int heightPixels;
public Screen() {
}
public Screen(int widthPixels, int heightPixels) {
this.widthPixels = widthPixels;
this.heightPixels = heightPixels;
}
@NonNull
@Override
public String toString() {
return "(" + widthPixels + "," + heightPixels + ")";
}
}
/**
* Get Screen Real Width 包含状态栏导航栏
*
* @return Real Width
*/
public static int getRealWidth() {
Display display = getDisplay(context);
if (display == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
return dm.widthPixels;
}
/**
* Get Screen Real Height 包含状态栏导航栏
*
* @return Real Height
*/
public static int getRealHeight() {
Display display = getDisplay(context);
if (display == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
return dm.heightPixels;
}
/**
* Get Display
*
* @param context Context for get WindowManager
* @return Display
*/
private static Display getDisplay(Context context) {
WindowManager wm;
if (context instanceof Activity) {
Activity activity = (Activity) context;
wm = activity.getWindowManager();
} else {
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
if (wm != null) {
return wm.getDefaultDisplay();
}
return null;
}
/**
* Get Screen Height 不含状态栏导航栏
*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* Get Screen Width 不含状态栏导航栏
*/
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
}
package com.base.appzxhy.utils
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
object IntentUtils {
fun intentAppDetailsSettings(context: Context): Intent {
val intent: Intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", context.packageName, null)
intent.setData(uri)
return intent
}
fun intentLocationSetting(): Intent {
val intent: Intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
return intent
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import org.json.JSONObject
object JsonUtils {
fun JSONObject.pullAll(jsonObject: JSONObject): JSONObject {
for (key in jsonObject.keys()) {
this.put(key, jsonObject.get(key))
}
return this
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
object KotlinExt {
fun Number.toFormatSize(count: Int = 1): String {
var suffix = "B"
var fSize = this.toDouble()
if (fSize > 1024) {
suffix = "KB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "MB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "GB"
fSize /= 1024.0
}
return String.format("%.${count}f %s", fSize, suffix)
}
fun Long.toFormatTime(): String {
return SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime2(): String {
return SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime3(): String {
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime4(): String {
return SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).format(this)
}
fun Long.toFormatMinute(): String {
return SimpleDateFormat("mm", Locale.ENGLISH).format(this)
}
fun Long.toFormatHHMinute(): String {
return SimpleDateFormat("HH:mm", Locale.ENGLISH).format(this)
}
fun Array<String>.array2String(): String {
val stringBuilder = StringBuilder()
forEach {
stringBuilder.append(it)
}
return stringBuilder.toString()
}
fun currentDate(): String {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val currentDate = Calendar.getInstance().time
return dateFormat.format(currentDate)
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.content.Context
import android.os.LocaleList
import java.util.Locale
object LanguageUtils {
fun getSystemLanguage(): String {
return Locale.getDefault().language
}
val supportLanguage = listOf(
Locale.ENGLISH.language,
Locale.PRC.language,
Locale("pt", "BR").language,
Locale("es").language,
Locale.FRENCH.language,
Locale("de").language,
Locale("th", "TH").language,
Locale("in", "ID").language,
Locale("ms", "MY").language,
Locale("vi", "VN").language,
Locale("ja", "JP").language,
Locale("it", "IT").language,
Locale("ko", "KR").language,
Locale("nl", "NL").language,
Locale("zh", "TW").language,
Locale("tr", "TR").language
)
fun getSystemLanguageDefault(): String {
var systemLanguage = getSystemLanguage()
if (!supportLanguage.contains(systemLanguage)) {
systemLanguage = Locale.ENGLISH.language
}
return systemLanguage
}
fun isSupportSystemLanguage(): Boolean {
return supportLanguage.contains(getSystemLanguage())
}
fun changeAppLanguage(context: Context, languageCountry: String) {
val config = context.resources.configuration
val lc = languageCountry.split("_")
val locale = if (lc.size == 2) {
Locale(lc[0], lc[1])
} else {
Locale(lc[0])
}
//Android 7.0以上的方法
config.setLocale(locale)
config.setLocales(LocaleList(locale))
context.createConfigurationContext(config)
context.resources.updateConfiguration(config, context.resources.displayMetrics)
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.util.Log
import com.base.appzxhy.BuildConfig
object LogEx {
val isOpen = true
val filterTAG = arrayOf(
"",
)
fun logDebug(tag: String, content: String, isMust: Boolean = false) {
if (isMust) {
Log.e(tag, content)
} else {
if (!isOpen) return
if (filterTAG.contains(tag)) return
if (BuildConfig.DEBUG) {
Log.e(tag, content)
}
}
}
}
\ No newline at end of file
package com.base.locationsharewhite.utils
import android.Manifest
import android.app.Activity
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import androidx.core.app.ActivityCompat
import com.base.appzxhy.utils.ActivityLauncher
import com.base.appzxhy.utils.IntentUtils.intentAppDetailsSettings
import com.base.appzxhy.utils.LogEx
object PermissionUtils {
fun Context.areNotificationsEnabled(): Boolean {
val notificationManager =
this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val flag = notificationManager.areNotificationsEnabled()
return flag
}
fun Context.checkStorePermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager()
} else {
val readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
val writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
}
}
fun Context.checkNotificationPermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
} else {
return true
}
}
fun Context.checkAllLocationPermission(): Boolean {
return checkLocationPermission() && checkBackgroundLocationPermission()
}
fun Context.checkLocationPermission(): Boolean {
val fineLocationPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
val accessCoarsePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
return fineLocationPermission == PackageManager.PERMISSION_GRANTED && accessCoarsePermission == PackageManager.PERMISSION_GRANTED;
}
fun Activity.checkLocationPermissionDeniedByUser(): Boolean {
val deniedByUser1 =
!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
val deniedByUser2 =
!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)
LogEx.logDebug("checkLocationPermissionDeniedByUser", "accessCoarsePermission=$deniedByUser1")
LogEx.logDebug("checkLocationPermissionDeniedByUser", "fineLocationPermission=$deniedByUser2")
return deniedByUser1 && deniedByUser2
}
fun Context.checkBackgroundLocationPermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
) == PackageManager.PERMISSION_GRANTED
} else {
true
}
}
fun Activity.checkBackgroundLocationPermissionDeniedByUser(): Boolean {
val deniedByUser1 =
!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
return deniedByUser1
}
fun Context.requestStoragePermission(
launcher: ActivityLauncher,
jumpAction: (() -> Unit)? = null,
result: (flag: Boolean) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent =
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.addCategory("android.intent.category.DEFAULT")
intent.data = Uri.parse("package:${packageName}")
jumpAction?.invoke()
launcher.launch(intent) {
result.invoke(checkStorePermission())
}
} else {
launcher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { map ->
result(map.values.all { it })
}
}
}
fun Activity.requestLocationAllowAllTime(
launcher: ActivityLauncher,
jumpOutAction: (() -> Unit)? = null,//跳转到设置
permissionAllowCallBack: (() -> Unit)? = null//权限同意
) {
val TAG = "requestLocationAllowAllTime"
launcher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
)
) { map ->
val result = map.values.all { it }
LogEx.logDebug(TAG, "定位权限回调 result=$result")
if (result) {
//跳转到后台位置设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
launcher.launch(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { map ->
val backLocationResult = map.values.all { it }
LogEx.logDebug(TAG, "后台位置权限回调 backLocationResult=$backLocationResult")
if (backLocationResult) {
// toast("权限请求完毕")
permissionAllowCallBack?.invoke()
} else {
val userBackLocationDeny = this.checkBackgroundLocationPermissionDeniedByUser()
LogEx.logDebug(TAG, "userBackLocationDeny userBackLocationDeny=$userBackLocationDeny 跳转设置")
if (userBackLocationDeny) {
jumpOutAction?.invoke()
launcher.launch(intentAppDetailsSettings(this))
}
}
}
} else {
permissionAllowCallBack?.invoke()
// toast("权限请求完毕")
}
} else {
val userDeny = checkLocationPermissionDeniedByUser()
LogEx.logDebug(TAG, "userDeny userDeny=$userDeny 跳转设置")
if (userDeny) {
jumpOutAction?.invoke()
launcher.launch(intentAppDetailsSettings(this))
}
}
}
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.content.Context
import com.base.appzxhy.BuildConfig
import com.reyun.solar.engine.OnAttributionListener
import com.reyun.solar.engine.OnInitializationCallback
import com.reyun.solar.engine.SolarEngineConfig
import com.reyun.solar.engine.SolarEngineManager
import org.json.JSONObject
object SolarEngineUtils {
private val TAG = "SolarEngineUtils"
val solarkey = "bd26f9b9ade9818d"
fun Context.initSolarEngine(gdprDeny: Boolean = false) {
val configBuilder = SolarEngineConfig.Builder()
if (BuildConfig.DEBUG) {
configBuilder.logEnabled() //开启本地调试日志
}
if (gdprDeny) {
configBuilder.isGDPRArea = true
configBuilder.adPersonalizationEnabled = true
configBuilder.adUserDataEnabled = true
}
configBuilder.isCoppaEnabled = true
configBuilder.setKidsAppEnabled(true)
configBuilder.fbAppID = ""
val config = configBuilder.build()
SolarEngineManager.getInstance().initialize(this, solarkey, config,
OnInitializationCallback { code ->
if (code == 0) {
//初始化成功
config.setOnAttributionListener(object : OnAttributionListener {
override fun onAttributionSuccess(attribution: JSONObject) {
//获取归因结果成功时执行的动作
// EventUtils.event("source_atrribute", ext = attribution)
}
override fun onAttributionFail(errorCode: Int) {
//获取归因结果失败时执行的动作
// EventUtils.event("SolarEngineManager onAttributionFail errorCode=$errorCode")
}
})
} else {
//初始化失败,具体失败原因参考下方code码释义
// EventUtils.event("SolarEngineManager init error code=$code")
}
})
}
}
\ No newline at end of file
import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.LogEx
object SpStringUtils {
private val TAG = "SpStringUtils"
const val _KEY = ""
fun getSpStringList(key: String): List<String> {
val sp = AppPreferences.getInstance().getString(key, "")
return if (sp.equals("")) {
listOf()
} else {
sp.split("|||")
}
}
fun addSpString(key: String, value: String) {
LogEx.logDebug(TAG, "key=$key value=$value")
val list = getSpStringList(key).toMutableList()
list.add(value)
val string = list.joinToString(separator = "|||")
AppPreferences.getInstance().put(key, string)
}
fun deleteSpString(key: String, value: String) {
val list = getSpStringList(key).toMutableList()
list.remove(value)
val string = list.joinToString(separator = "|||")
AppPreferences.getInstance().put(key, string)
}
}
\ No newline at end of file
package com.base.appzxhy.utils
import android.content.Context
import android.widget.Toast
import com.base.appzxhy.BuildConfig
object ToastUtils {
fun Context.toast(content: String, isMust: Boolean = false) {
if (BuildConfig.DEBUG || isMust) {
Toast.makeText(this, content, Toast.LENGTH_SHORT).show()
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="1000"
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="1000"
android:fromAlpha="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.LocalWeatherWhite" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">LocalWeatherWhite</string>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.LocalWeatherWhite" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.LocalWeatherWhite" parent="Base.Theme.LocalWeatherWhite" />
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
\ No newline at end of file
package com.base.appzxhy
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}
\ No newline at end of file
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
\ No newline at end of file
[versions]
agp = "8.3.0"
kotlin = "1.8.0"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
immersionbar = "3.2.2"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
immersionbar = { module = "com.geyifeng.immersionbar:immersionbar", version.ref = "immersionbar" }
immersionbar-ktx = { module = "com.geyifeng.immersionbar:immersionbar-ktx", version.ref = "immersionbar" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
#Mon Dec 16 10:01:19 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://maven.google.com'")
maven("https://s01.oss.sonatype.org/content/groups/public")
maven("https://jitpack.io")
maven("https://android-sdk.is.com")
maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
maven("https://artifact.bytedance.com/repository/pangle")
maven("https://dl-maven-android.mintegral.com/repository/se_sdk_for_android/")
}
}
rootProject.name = "appzxhy"
include(":app")
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment