Сравнить коммиты
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
6dadf5e7c3 | ||
|
|
39e9c171c4 | ||
|
|
bcb5985cef | ||
|
|
eb868056bf | ||
|
|
94e094e648 | ||
|
|
25c0434e4c | ||
|
|
3afcfa17d0 | ||
|
|
02263d5fd9 | ||
|
|
a884b2f3d7 |
@@ -9,8 +9,8 @@ android {
|
||||
buildConfigField 'boolean', 'HIDDEN_APP', 'false'
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
versionCode 70
|
||||
versionName '6.9'
|
||||
versionCode 73
|
||||
versionName '6.12'
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
@@ -47,14 +47,14 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.material:material:1.5.0-alpha01'
|
||||
implementation 'com.google.android.material:material:1.5.0-alpha02'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||
implementation 'androidx.test:core-ktx:1.4.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.1'
|
||||
implementation "androidx.core:core-ktx:1.6.0"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.1'
|
||||
googleImplementation platform('com.google.firebase:firebase-bom:28.2.1')
|
||||
googleImplementation 'com.google.firebase:firebase-core'
|
||||
googleImplementation 'com.google.firebase:firebase-analytics'
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
|
||||
<uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE" />
|
||||
<uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT" />
|
||||
|
||||
<uses-feature android:name="android.hardware.location.network" />
|
||||
<uses-feature android:name="android.hardware.location.gps" />
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2021 Anton Tananaev (anton@traccar.org)
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package org.traccar.client
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.PreferenceManager
|
||||
|
||||
class BatteryOptimizationHelper {
|
||||
|
||||
private fun showDialog(context: Context, onSuccess: () -> Unit) {
|
||||
val builder = AlertDialog.Builder(context)
|
||||
builder.setMessage(context.getString(R.string.request_exception))
|
||||
builder.setPositiveButton(android.R.string.ok) { _, _ -> onSuccess() }
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
builder.show()
|
||||
}
|
||||
|
||||
private fun requestVendorException(context: Context) {
|
||||
val vendorIntentList = listOf(
|
||||
Intent().setComponent(ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
|
||||
Intent().setComponent(ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
|
||||
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity")),
|
||||
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
|
||||
Intent().setComponent(ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
|
||||
Intent().setComponent(ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
|
||||
Intent().setComponent(ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
|
||||
Intent().setComponent(ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
|
||||
Intent().setComponent(ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
|
||||
Intent().setComponent(ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
|
||||
Intent().setComponent(ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
|
||||
Intent().setComponent(ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
|
||||
Intent().setComponent(ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
|
||||
Intent().setComponent(ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity")),
|
||||
)
|
||||
for (vendorIntent in vendorIntentList) {
|
||||
if (context.packageManager.resolveActivity(vendorIntent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
|
||||
try {
|
||||
context.startActivity(vendorIntent)
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun requestException(context: Context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
if (!sharedPreferences.getBoolean(KEY_EXCEPTION_REQUESTED, false)) {
|
||||
sharedPreferences.edit().putBoolean(KEY_EXCEPTION_REQUESTED, true).apply()
|
||||
val powerManager = context.getSystemService(PowerManager::class.java)
|
||||
if (!powerManager.isIgnoringBatteryOptimizations(context.packageName)) {
|
||||
showDialog(context) {
|
||||
try {
|
||||
context.startActivity(Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
requestVendorException(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_EXCEPTION_REQUESTED = "exceptionRequested"
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class DatabaseHelper(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAM
|
||||
fun onComplete(success: Boolean, result: T)
|
||||
}
|
||||
|
||||
private abstract class DatabaseAsyncTask<T>(val handler: DatabaseHandler<T>) : AsyncTask<Unit, Unit, T?>() {
|
||||
private abstract class DatabaseAsyncTask<T>(val handler: DatabaseHandler<T?>) : AsyncTask<Unit, Unit, T?>() {
|
||||
|
||||
private var error: RuntimeException? = null
|
||||
|
||||
@@ -46,7 +46,7 @@ class DatabaseHelper(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAM
|
||||
protected abstract fun executeMethod(): T
|
||||
|
||||
override fun onPostExecute(result: T?) {
|
||||
result?.let { handler.onComplete(error == null, result) }
|
||||
handler.onComplete(error == null, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class DatabaseHelper(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAM
|
||||
db.insertOrThrow("position", null, values)
|
||||
}
|
||||
|
||||
fun insertPositionAsync(position: Position, handler: DatabaseHandler<Unit>) {
|
||||
fun insertPositionAsync(position: Position, handler: DatabaseHandler<Unit?>) {
|
||||
object : DatabaseAsyncTask<Unit>(handler) {
|
||||
override fun executeMethod() {
|
||||
insertPosition(position)
|
||||
@@ -138,7 +138,7 @@ class DatabaseHelper(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAM
|
||||
}
|
||||
}
|
||||
|
||||
fun deletePositionAsync(id: Long, handler: DatabaseHandler<Unit>) {
|
||||
fun deletePositionAsync(id: Long, handler: DatabaseHandler<Unit?>) {
|
||||
object : DatabaseAsyncTask<Unit>(handler) {
|
||||
override fun executeMethod() {
|
||||
deletePosition(id)
|
||||
|
||||
@@ -90,7 +90,10 @@ class MainFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListene
|
||||
findPreference<Preference>(KEY_ANGLE)?.onPreferenceChangeListener = numberValidationListener
|
||||
|
||||
alarmManager = requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
alarmIntent = PendingIntent.getBroadcast(activity, 0, Intent(activity, AutostartReceiver::class.java), 0)
|
||||
val originalIntent = Intent(activity, AutostartReceiver::class.java)
|
||||
originalIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
|
||||
alarmIntent = PendingIntent.getBroadcast(activity, 0, originalIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (sharedPreferences.getBoolean(KEY_STATUS, false)) {
|
||||
startTrackingService(checkPermission = true, initialPermission = false)
|
||||
}
|
||||
@@ -226,6 +229,7 @@ class MainFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListene
|
||||
AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
ALARM_MANAGER_INTERVAL.toLong(), ALARM_MANAGER_INTERVAL.toLong(), alarmIntent
|
||||
)
|
||||
BatteryOptimizationHelper().requestException(requireContext())
|
||||
} else {
|
||||
sharedPreferences.edit().putBoolean(KEY_STATUS, false).apply()
|
||||
val preference = findPreference<TwoStatePreference>(KEY_STATUS)
|
||||
|
||||
@@ -104,8 +104,8 @@ class TrackingController(private val context: Context) : PositionListener, Netwo
|
||||
|
||||
private fun write(position: Position) {
|
||||
log("write", position)
|
||||
databaseHelper.insertPositionAsync(position, object : DatabaseHandler<Unit> {
|
||||
override fun onComplete(success: Boolean, result: Unit) {
|
||||
databaseHelper.insertPositionAsync(position, object : DatabaseHandler<Unit?> {
|
||||
override fun onComplete(success: Boolean, result: Unit?) {
|
||||
if (success) {
|
||||
if (isOnline && isWaiting) {
|
||||
read()
|
||||
@@ -139,8 +139,8 @@ class TrackingController(private val context: Context) : PositionListener, Netwo
|
||||
|
||||
private fun delete(position: Position) {
|
||||
log("delete", position)
|
||||
databaseHelper.deletePositionAsync(position.id, object : DatabaseHandler<Unit> {
|
||||
override fun onComplete(success: Boolean, result: Unit) {
|
||||
databaseHelper.deletePositionAsync(position.id, object : DatabaseHandler<Unit?> {
|
||||
override fun onComplete(success: Boolean, result: Unit?) {
|
||||
if (success) {
|
||||
read()
|
||||
} else {
|
||||
|
||||
@@ -49,7 +49,7 @@ class TrackingService : Service() {
|
||||
stopForeground(true)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
stopSelfResult(startId)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class TrackingService : Service() {
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ECLAIR)
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent)
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ abstract class WakefulBroadcastReceiver : BroadcastReceiver() {
|
||||
}
|
||||
}
|
||||
|
||||
fun completeWakefulIntent(intent: Intent): Boolean {
|
||||
val id = intent.getIntExtra(EXTRA_WAKE_LOCK_ID, 0)
|
||||
fun completeWakefulIntent(intent: Intent?): Boolean {
|
||||
val id = intent?.getIntExtra(EXTRA_WAKE_LOCK_ID, 0) ?: 0
|
||||
if (id == 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -46,4 +46,5 @@
|
||||
<string name="hidden_app_name">Device Settings</string>
|
||||
<string name="hidden_alert">The app has been hidden. To open it again please dial 8722227 (TRACCAR).</string>
|
||||
<string name="error_msg_invalid_url">Please enter a valid http:// or https:// URL</string>
|
||||
<string name="request_exception">To continuously collect location data please turn off battery optimization for the app.</string>
|
||||
</resources>
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.5.21'
|
||||
ext.kotlin_version = '1.5.30'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.0-beta05'
|
||||
classpath 'com.google.gms:google-services:4.3.8'
|
||||
classpath 'com.android.tools.build:gradle:7.0.1'
|
||||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user