From 352380c79c29355aa7dc2f7e5c3dc0c76f82b058 Mon Sep 17 00:00:00 2001 From: Erwan Finot Date: Sun, 13 Sep 2020 17:20:45 +0200 Subject: [PATCH 1/3] Fix CarManager for Android 10 and use AndroidX --- app/build.gradle | 12 ++-- .../autovolume/ExampleInstrumentedTest.java | 26 -------- app/src/main/AndroidManifest.xml | 22 +------ .../microntek/CarManageCallback.java | 5 +- .../microntek/CarManager.java | 10 ++-- .../microntek/ICarManageCallback.java | 4 +- .../microntek/ICarService.java | 8 +-- .../{android => com}/microntek/IRTable.java | 2 +- .../{android => com}/microntek/MTCData.java | 2 +- .../autovolume/AutoVolumeBooter.java | 39 +++++++++++- .../threecats/autovolume/CanBusDriver.java | 3 +- .../threecats/autovolume/MainActivity.java | 2 + .../threecats/autovolume/TestVolActivity.java | 3 +- .../threecats/autovolume/VolumeService.java | 60 +++++++++++++++++-- .../autovolume/VolumeServiceWatchdog.java | 22 +++++++ .../res/layout-nodpi/activity_test_vol.xml | 4 +- app/src/main/res/values/strings.xml | 2 + build.gradle | 2 +- gradle.properties | 2 + gradle/wrapper/gradle-wrapper.properties | 4 +- 20 files changed, 155 insertions(+), 79 deletions(-) delete mode 100644 app/src/androidTest/java/com/microntek/threecats/autovolume/ExampleInstrumentedTest.java rename app/src/main/java/{android => com}/microntek/CarManageCallback.java (55%) rename app/src/main/java/{android => com}/microntek/CarManager.java (96%) rename app/src/main/java/{android => com}/microntek/ICarManageCallback.java (99%) rename app/src/main/java/{android => com}/microntek/ICarService.java (98%) rename app/src/main/java/{android => com}/microntek/IRTable.java (99%) rename app/src/main/java/{android => com}/microntek/MTCData.java (99%) create mode 100644 app/src/main/java/com/microntek/threecats/autovolume/VolumeServiceWatchdog.java diff --git a/app/build.gradle b/app/build.gradle index e46455d..4552313 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '27.0.3' + compileSdkVersion 29 + buildToolsVersion '29.0.3' defaultConfig { applicationId "com.microntek.threecats.autovolume" minSdkVersion 21 - targetSdkVersion 22 + targetSdkVersion 29 versionCode 4 versionName "1.2.1" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } buildTypes { release { @@ -21,9 +21,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support.constraint:constraint-layout:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.12' - androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', { + androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { exclude group: 'com.android.support', module: 'support-annotations' }) } diff --git a/app/src/androidTest/java/com/microntek/threecats/autovolume/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/microntek/threecats/autovolume/ExampleInstrumentedTest.java deleted file mode 100644 index f2e1dbc..0000000 --- a/app/src/androidTest/java/com/microntek/threecats/autovolume/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.microntek.threecats.autovolume; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.microntek.threecats.autovolume", appContext.getPackageName()); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e927046..ba87ab6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + + - - - + \ No newline at end of file diff --git a/app/src/main/java/android/microntek/CarManageCallback.java b/app/src/main/java/com/microntek/CarManageCallback.java similarity index 55% rename from app/src/main/java/android/microntek/CarManageCallback.java rename to app/src/main/java/com/microntek/CarManageCallback.java index 24ebc63..992b9f5 100644 --- a/app/src/main/java/android/microntek/CarManageCallback.java +++ b/app/src/main/java/com/microntek/CarManageCallback.java @@ -1,10 +1,9 @@ -package android.microntek; +package com.microntek; -import android.microntek.ICarManageCallback.Stub; import android.os.Bundle; import android.os.RemoteException; -public class CarManageCallback extends Stub { +public class CarManageCallback extends ICarManageCallback.Stub { public void onStatusChanged(String type, Bundle bundle) throws RemoteException { } } diff --git a/app/src/main/java/android/microntek/CarManager.java b/app/src/main/java/com/microntek/CarManager.java similarity index 96% rename from app/src/main/java/android/microntek/CarManager.java rename to app/src/main/java/com/microntek/CarManager.java index d7e6e2d..83db4cf 100644 --- a/app/src/main/java/android/microntek/CarManager.java +++ b/app/src/main/java/com/microntek/CarManager.java @@ -1,6 +1,8 @@ -package android.microntek; +package com.microntek; -import android.microntek.ICarService.Stub; +import com.microntek.ICarService.Stub; + +import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -43,7 +45,7 @@ public CarManager() { private static IBinder getCarService() { try { - Class localClass = Class.forName("android.os.ServiceManager"); + @SuppressLint("PrivateApi") Class localClass = Class.forName("android.os.ServiceManager"); Method getService = localClass.getMethod("getService", new Class[] {String.class}); if(getService != null) { @@ -203,4 +205,4 @@ public void putDataChanage(String type, String state) { } catch (Exception e) { } } -} +} \ No newline at end of file diff --git a/app/src/main/java/android/microntek/ICarManageCallback.java b/app/src/main/java/com/microntek/ICarManageCallback.java similarity index 99% rename from app/src/main/java/android/microntek/ICarManageCallback.java rename to app/src/main/java/com/microntek/ICarManageCallback.java index b2c478c..a2f1113 100644 --- a/app/src/main/java/android/microntek/ICarManageCallback.java +++ b/app/src/main/java/com/microntek/ICarManageCallback.java @@ -1,4 +1,4 @@ -package android.microntek; +package com.microntek; import android.os.Binder; import android.os.Bundle; @@ -92,4 +92,4 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws } void onStatusChanged(String str, Bundle bundle) throws RemoteException; -} +} \ No newline at end of file diff --git a/app/src/main/java/android/microntek/ICarService.java b/app/src/main/java/com/microntek/ICarService.java similarity index 98% rename from app/src/main/java/android/microntek/ICarService.java rename to app/src/main/java/com/microntek/ICarService.java index 55011be..b91bdb6 100644 --- a/app/src/main/java/android/microntek/ICarService.java +++ b/app/src/main/java/com/microntek/ICarService.java @@ -1,4 +1,4 @@ -package android.microntek; +package com.microntek; import android.os.Binder; import android.os.IBinder; @@ -456,12 +456,12 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws return true; case TRANSACTION_registerCallback /*15*/: data.enforceInterface(DESCRIPTOR); - registerCallback(android.microntek.ICarManageCallback.Stub.asInterface(data.readStrongBinder())); + registerCallback(ICarManageCallback.Stub.asInterface(data.readStrongBinder())); reply.writeNoException(); return true; case TRANSACTION_unregisterCallback /*16*/: data.enforceInterface(DESCRIPTOR); - unregisterCallback(android.microntek.ICarManageCallback.Stub.asInterface(data.readStrongBinder())); + unregisterCallback(ICarManageCallback.Stub.asInterface(data.readStrongBinder())); reply.writeNoException(); return true; case TRANSACTION_setParameters /*17*/: @@ -527,4 +527,4 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws int setParameters(String str) throws RemoteException; void unregisterCallback(ICarManageCallback iCarManageCallback) throws RemoteException; -} +} \ No newline at end of file diff --git a/app/src/main/java/android/microntek/IRTable.java b/app/src/main/java/com/microntek/IRTable.java similarity index 99% rename from app/src/main/java/android/microntek/IRTable.java rename to app/src/main/java/com/microntek/IRTable.java index bb4ac12..b454d0b 100644 --- a/app/src/main/java/android/microntek/IRTable.java +++ b/app/src/main/java/com/microntek/IRTable.java @@ -1,4 +1,4 @@ -package android.microntek; +package com.microntek; public class IRTable { public static final int IR_AB = 363; diff --git a/app/src/main/java/android/microntek/MTCData.java b/app/src/main/java/com/microntek/MTCData.java similarity index 99% rename from app/src/main/java/android/microntek/MTCData.java rename to app/src/main/java/com/microntek/MTCData.java index 09320ea..6deb78e 100644 --- a/app/src/main/java/android/microntek/MTCData.java +++ b/app/src/main/java/com/microntek/MTCData.java @@ -1,4 +1,4 @@ -package android.microntek; +package com.microntek; public class MTCData { public static final int MAX_BALANCE = 28; diff --git a/app/src/main/java/com/microntek/threecats/autovolume/AutoVolumeBooter.java b/app/src/main/java/com/microntek/threecats/autovolume/AutoVolumeBooter.java index b20c029..aa7f799 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/AutoVolumeBooter.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/AutoVolumeBooter.java @@ -1,13 +1,48 @@ package com.microntek.threecats.autovolume; +import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Build; + +import java.util.Objects; public class AutoVolumeBooter extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - Intent i = new Intent(context, VolumeService.class); - context.startService(i); + if (Objects.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED) || + Objects.equals(intent.getAction(), Intent.ACTION_SCREEN_ON)) { + + Intent intentVolumeService = new Intent(context, VolumeService.class); + intentVolumeService.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + + if (isMyServiceRunning(context)) { + context.stopService(intentVolumeService); + } + + startService(context, intentVolumeService); + } + } + + private boolean isMyServiceRunning(Context context) { + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + + if (manager != null) { + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + if (VolumeService.class.getName().equals(service.service.getClassName())) { + return true; + } + } + } + return false; + } + + private void startService(Context context, Intent intent) { + if (Build.VERSION.SDK_INT < 26) { + context.startService(intent); + } else { + context.startForegroundService(intent); + } } } diff --git a/app/src/main/java/com/microntek/threecats/autovolume/CanBusDriver.java b/app/src/main/java/com/microntek/threecats/autovolume/CanBusDriver.java index b3b8b3d..fa27aa8 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/CanBusDriver.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/CanBusDriver.java @@ -1,9 +1,10 @@ package com.microntek.threecats.autovolume; -import android.microntek.CarManager; import android.os.Handler; import android.util.Log; +import com.microntek.CarManager; + public class CanBusDriver { private static final String TAG = CanBusDriver.class.getSimpleName(); diff --git a/app/src/main/java/com/microntek/threecats/autovolume/MainActivity.java b/app/src/main/java/com/microntek/threecats/autovolume/MainActivity.java index 7bb2fce..b3b018f 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/MainActivity.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/MainActivity.java @@ -216,6 +216,8 @@ public void onStopTrackingTouch(SeekBar seekBar) { staticVolumeView.setText("Static Volume: " + staticVolume); debugVolView = (TextView) findViewById(R.id.debugVolView); + + this.startService(new Intent(this, VolumeService.class)); } private void switchSend(boolean on) { diff --git a/app/src/main/java/com/microntek/threecats/autovolume/TestVolActivity.java b/app/src/main/java/com/microntek/threecats/autovolume/TestVolActivity.java index 71ff677..d9ba175 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/TestVolActivity.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/TestVolActivity.java @@ -2,13 +2,14 @@ import android.app.Activity; import android.content.Intent; -import android.microntek.CarManager; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; +import com.microntek.CarManager; + public class TestVolActivity extends Activity { private static final String TAG = TestVolActivity.class.getName(); diff --git a/app/src/main/java/com/microntek/threecats/autovolume/VolumeService.java b/app/src/main/java/com/microntek/threecats/autovolume/VolumeService.java index a539d2a..4fa7f26 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/VolumeService.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/VolumeService.java @@ -1,13 +1,16 @@ package com.microntek.threecats.autovolume; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; -import android.microntek.CarManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -20,6 +23,10 @@ import android.widget.ImageView; import android.widget.TextView; +import com.microntek.CarManager; + +import java.util.Objects; + public class VolumeService extends Service implements CanBusReceiver.Callback { private static final int MAX_REV = 5000; // RPM private static final int MAX_SPEED = 200; // km/h @@ -45,6 +52,8 @@ public class VolumeService extends Service implements CanBusReceiver.Callback { private int speed; private boolean revBarChanging; private boolean speedBarChanging; + private boolean mServiceInitialized; + private boolean mForceRestart; public int getEffect() { return effect; @@ -163,13 +172,24 @@ VolumeService getService() { } } - private final IBinder mBinder = new VolumeBinder(); + private final VolumeBinder mBinder = new VolumeBinder(); @Override public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + if (effect == 0) { - stopSelf(); + //stopSelf(); } + + if (mServiceInitialized) { + return START_STICKY; + } + + startForeground(1556, createNotification()); + mServiceInitialized = true; + mForceRestart = true; + return START_STICKY; } @@ -184,6 +204,9 @@ public void onCreate() { Log.d(TAG, "Service is UP!"); + mServiceInitialized = false; + mForceRestart = false; + effect = getSharedPreferences("main", 0).getInt("effect", 0); monitor = getSharedPreferences("main", 0).getBoolean("monitor", false); @@ -209,11 +232,38 @@ public void onReceive(Context context, Intent intent) { initOVerlay(); } + private Notification createNotification() { + Notification.Builder notification; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelId = "VolumeService"; + + NotificationChannel channel = new NotificationChannel(channelId, getString(R.string.PersistentNotificationChannel), NotificationManager.IMPORTANCE_NONE); + NotificationManager notificationManager = getSystemService(NotificationManager.class); + Objects.requireNonNull(notificationManager).createNotificationChannel(channel); + + notification = new Notification.Builder(this, channelId); + } else { + notification = new Notification.Builder(this); + } + + return notification.setContentTitle(getString(R.string.app_name)) + .setContentText(getString(R.string.VolumeServiceDescription)) + .setOngoing(true) + .build(); + } + @Override public void onDestroy() { super.onDestroy(); - Log.d(TAG, "Service is DOWN!"); + if (mForceRestart) { + VolumeServiceWatchdog.scheduleServiceRestart(this); + } + + if (mServiceInitialized) { + mServiceInitialized = false; + } unregisterReceiver(volumeReceiver); @@ -222,6 +272,8 @@ public void onDestroy() { canBusDriver.stop(); h.removeCallbacks(r); + + Log.d(TAG, "Service is DOWN!"); } interface UICallback { diff --git a/app/src/main/java/com/microntek/threecats/autovolume/VolumeServiceWatchdog.java b/app/src/main/java/com/microntek/threecats/autovolume/VolumeServiceWatchdog.java new file mode 100644 index 0000000..43fdd6a --- /dev/null +++ b/app/src/main/java/com/microntek/threecats/autovolume/VolumeServiceWatchdog.java @@ -0,0 +1,22 @@ +package com.microntek.threecats.autovolume; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.SystemClock; + +class VolumeServiceWatchdog { + public static void scheduleServiceRestart(Context context) { + // WORKAROUND: Do not know why MTCD Android does not respect START_STICKY + + Intent restartServiceIntent = new Intent(context, VolumeService.class); + restartServiceIntent.setPackage(context.getPackageName()); + + PendingIntent restartServicePendingIntent = PendingIntent.getService(context, 1556, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT); + AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + SERVICE_RESTART_DELAY_MS, restartServicePendingIntent); + } + + private static final int SERVICE_RESTART_DELAY_MS = 100; +} diff --git a/app/src/main/res/layout-nodpi/activity_test_vol.xml b/app/src/main/res/layout-nodpi/activity_test_vol.xml index 6b09fab..bab3c87 100644 --- a/app/src/main/res/layout-nodpi/activity_test_vol.xml +++ b/app/src/main/res/layout-nodpi/activity_test_vol.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f822940..c1f2d25 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ AutoVolume + Service is now active. + Persistent notification diff --git a/build.gradle b/build.gradle index eccff49..2deb66d 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.1' + classpath 'com.android.tools.build:gradle:4.0.1' // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index aac7c9b..9e6fce1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,8 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. +android.enableJetifier=true +android.useAndroidX=true org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 46fb1e3..82ecb25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Apr 15 13:48:15 BST 2018 +#Sun Sep 13 11:09:39 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip From bc994236ea15649a757ca57e72b6aa0d9bd0a62a Mon Sep 17 00:00:00 2001 From: Erwan Finot Date: Thu, 23 Feb 2023 23:00:00 +0100 Subject: [PATCH 2/3] Avoid loud surprises when engine stopped (again) Some cars are sending a speed of 327km/h when stopped. --- .../com/microntek/threecats/autovolume/CanBusReceiver.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java b/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java index e4a230c..9744788 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java @@ -78,9 +78,14 @@ public void onReceive(Context context, Intent intent) { double speed = 0; if (rev > 0) { speed = ((0xFF & data[5]) * 256 + (0xFF & data[6])) * 0.01d; + + // some cars are jumping to 327km/h when stopped, set to 0 too + if (rev < 3000 && speed == 327) { + speed = 0; + } } bundle.putDouble(SPEED, speed); - + double battery = ((0xFF & data[7]) * 256 + (0xFF & data[8])) * 0.01d; bundle.putDouble(BATT, battery); From 511062b0f46c0f2faef90f7aeeb0471f480bd1de Mon Sep 17 00:00:00 2001 From: Erwan Finot Date: Fri, 24 Feb 2023 18:58:39 +0100 Subject: [PATCH 3/3] Avoid loud surprises when engine stopped (again) 327.00km/h may be too precise. --- .../java/com/microntek/threecats/autovolume/CanBusReceiver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java b/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java index 9744788..7082655 100644 --- a/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java +++ b/app/src/main/java/com/microntek/threecats/autovolume/CanBusReceiver.java @@ -80,7 +80,7 @@ public void onReceive(Context context, Intent intent) { speed = ((0xFF & data[5]) * 256 + (0xFF & data[6])) * 0.01d; // some cars are jumping to 327km/h when stopped, set to 0 too - if (rev < 3000 && speed == 327) { + if (rev < 3000 && speed > 320.00) { speed = 0; } }