2020-01-09 10:44:32 +01:00
/ * Copyright ( C ) 2015 - 2020 Andreas Shimokawa , Carsten Pfeiffer , Daniele
2019-02-13 20:43:30 +01:00
Gobbetti , Martin , Matthieu Baerts , Normano64 , Pavel Elagin , Taavi Eomäe
2017-03-10 14:53:19 +01:00
This file is part of Gadgetbridge .
Gadgetbridge is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Gadgetbridge is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>. */
2015-05-01 09:36:10 +02:00
package nodomain.freeyourgadget.gadgetbridge ;
2016-05-20 21:49:25 +02:00
import android.annotation.TargetApi ;
2015-05-01 09:36:10 +02:00
import android.app.Application ;
2018-02-14 21:27:24 +01:00
import android.app.NotificationChannel ;
2016-05-19 23:58:13 +02:00
import android.app.NotificationManager ;
2016-05-19 16:34:59 +02:00
import android.app.NotificationManager.Policy ;
2020-04-13 17:51:36 +02:00
import android.app.UiModeManager ;
2018-05-16 19:03:06 +02:00
import android.bluetooth.BluetoothAdapter ;
2015-05-01 09:36:10 +02:00
import android.content.Context ;
2015-12-07 23:33:32 +01:00
import android.content.Intent ;
2018-05-16 19:03:06 +02:00
import android.content.IntentFilter ;
2015-05-23 00:45:12 +02:00
import android.content.SharedPreferences ;
2017-10-19 21:52:38 +02:00
import android.content.pm.ApplicationInfo ;
import android.content.pm.PackageInfo ;
import android.content.pm.PackageManager ;
2017-07-31 22:49:05 +02:00
import android.content.res.Configuration ;
2016-04-23 23:24:56 +02:00
import android.content.res.Resources ;
2016-05-19 16:34:59 +02:00
import android.database.Cursor ;
2016-05-13 23:47:47 +02:00
import android.database.sqlite.SQLiteDatabase ;
2016-05-19 16:34:59 +02:00
import android.net.Uri ;
2015-06-06 00:10:38 +02:00
import android.os.Build ;
import android.os.Build.VERSION ;
2015-05-23 00:45:12 +02:00
import android.preference.PreferenceManager ;
2016-05-19 16:34:59 +02:00
import android.provider.ContactsContract.PhoneLookup ;
2015-06-21 10:18:41 +02:00
import android.util.Log ;
2016-04-23 23:24:56 +02:00
import android.util.TypedValue ;
2015-05-23 00:45:12 +02:00
2020-07-28 01:09:59 +02:00
import androidx.core.app.NotificationCompat ;
2019-05-09 14:55:37 +02:00
import androidx.localbroadcastmanager.content.LocalBroadcastManager ;
2015-05-13 23:15:20 +02:00
import java.io.File ;
2015-07-08 23:03:34 +02:00
import java.io.IOException ;
2019-11-24 18:40:44 +01:00
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collections ;
2015-09-25 00:53:40 +02:00
import java.util.HashSet ;
2016-11-24 21:11:28 +01:00
import java.util.List ;
2017-07-31 22:49:05 +02:00
import java.util.Locale ;
2017-04-22 16:59:55 +02:00
import java.util.Set ;
2015-08-03 01:17:02 +02:00
import java.util.concurrent.TimeUnit ;
import java.util.concurrent.locks.Lock ;
import java.util.concurrent.locks.ReentrantLock ;
2015-05-13 23:15:20 +02:00
2015-08-03 01:17:02 +02:00
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler ;
2016-08-27 22:51:00 +02:00
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper ;
2016-05-16 23:54:51 +02:00
import nodomain.freeyourgadget.gadgetbridge.database.DBOpenHelper ;
2016-06-18 23:35:34 +02:00
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager ;
2016-04-17 19:52:51 +02:00
import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster ;
2019-05-20 21:53:53 +02:00
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession ;
2019-05-20 16:36:06 +02:00
import nodomain.freeyourgadget.gadgetbridge.entities.Device ;
2018-05-16 19:03:06 +02:00
import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothStateChangeReceiver ;
2016-11-24 21:11:28 +01:00
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice ;
2015-08-21 00:58:18 +02:00
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService ;
2016-02-02 17:33:24 +01:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser ;
2015-08-21 00:58:18 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService ;
2019-05-23 23:24:49 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType ;
2017-04-19 13:23:13 +02:00
import nodomain.freeyourgadget.gadgetbridge.service.NotificationCollectorMonitorService ;
2017-09-03 01:02:31 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils ;
2015-07-08 23:03:34 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils ;
2015-08-22 01:08:46 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.GB ;
2016-04-28 23:17:13 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs ;
2016-01-09 16:07:22 +01:00
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue ;
2016-04-25 23:18:55 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.Prefs ;
2015-05-30 17:28:03 +02:00
2019-05-23 23:24:49 +02:00
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.AMAZFITBIP ;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.AMAZFITCOR ;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.AMAZFITCOR2 ;
2019-06-18 22:07:43 +02:00
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.MIBAND ;
2019-05-24 23:46:20 +02:00
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.MIBAND2 ;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.MIBAND3 ;
2019-05-20 16:36:06 +02:00
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceType.fromKey ;
2020-03-03 18:01:39 +01:00
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID ;
2020-07-28 01:09:59 +02:00
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_ID ;
2015-10-26 23:32:03 +01:00
/ * *
* Main Application class that initializes and provides access to certain things like
* logging and DB access .
* /
2015-05-01 09:36:10 +02:00
public class GBApplication extends Application {
2015-08-03 01:17:02 +02:00
// Since this class must not log to slf4j, we use plain android.util.Log
private static final String TAG = " GBApplication " ;
2016-08-27 22:51:00 +02:00
public static final String DATABASE_NAME = " Gadgetbridge " ;
2015-05-01 09:36:10 +02:00
private static GBApplication context ;
2015-08-16 00:17:16 +02:00
private static final Lock dbLock = new ReentrantLock ( ) ;
2015-08-21 00:58:18 +02:00
private static DeviceService deviceService ;
2015-09-25 00:53:40 +02:00
private static SharedPreferences sharedPrefs ;
2016-02-02 17:33:24 +01:00
private static final String PREFS_VERSION = " shared_preferences_version " ;
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
2019-12-14 23:43:54 +01:00
private static final int CURRENT_PREFS_VERSION = 7 ;
2020-07-28 01:09:59 +02:00
private static final int ERROR_IN_GADGETBRIDGE_NOTIFICATION = 42 ;
2016-01-09 16:07:22 +01:00
private static LimitedQueue mIDSenderLookup = new LimitedQueue ( 16 ) ;
2016-04-25 23:18:55 +02:00
private static Prefs prefs ;
2016-04-28 23:17:13 +02:00
private static GBPrefs gbPrefs ;
2016-06-14 20:13:08 +02:00
private static LockHandler lockHandler ;
2016-05-20 22:04:30 +02:00
/ * *
* Note : is null on Lollipop and Kitkat
* /
2016-05-19 23:58:13 +02:00
private static NotificationManager notificationManager ;
2015-05-01 09:36:10 +02:00
2015-12-07 23:33:32 +01:00
public static final String ACTION_QUIT
= " nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit " ;
2017-07-31 22:49:05 +02:00
public static final String ACTION_LANGUAGE_CHANGE = " nodomain.freeyourgadget.gadgetbridge.gbapplication.action.language_change " ;
2019-09-01 22:09:09 +02:00
public static final String ACTION_NEW_DATA = " nodomain.freeyourgadget.gadgetbridge.action.new_data " ;
2017-04-27 07:52:11 +02:00
private static GBApplication app ;
2016-05-26 23:46:21 +02:00
private static Logging logging = new Logging ( ) {
@Override
protected String createLogDirectory ( ) throws IOException {
2017-04-27 07:52:11 +02:00
if ( GBEnvironment . env ( ) . isLocalTest ( ) ) {
return System . getProperty ( Logging . PROP_LOGFILES_DIR ) ;
} else {
File dir = FileUtils . getExternalFilesDir ( ) ;
return dir . getAbsolutePath ( ) ;
}
2016-05-26 23:46:21 +02:00
}
} ;
2017-07-31 22:49:05 +02:00
private static Locale language ;
2016-12-07 23:13:51 +01:00
private DeviceManager deviceManager ;
2018-05-16 19:03:06 +02:00
private BluetoothStateChangeReceiver bluetoothStateChangeReceiver ;
2015-12-07 23:33:32 +01:00
2016-07-08 22:35:52 +02:00
public static void quit ( ) {
GB . log ( " Quitting Gadgetbridge... " , GB . INFO , null ) ;
Intent quitIntent = new Intent ( GBApplication . ACTION_QUIT ) ;
LocalBroadcastManager . getInstance ( context ) . sendBroadcast ( quitIntent ) ;
GBApplication . deviceService ( ) . quit ( ) ;
2015-12-07 23:33:32 +01:00
}
2015-05-01 09:36:10 +02:00
public GBApplication ( ) {
context = this ;
2015-07-25 00:07:33 +02:00
// don't do anything here, add it to onCreate instead
2015-05-01 09:36:10 +02:00
}
2017-04-27 07:52:11 +02:00
public static Logging getLogging ( ) {
return logging ;
}
2015-08-21 00:58:18 +02:00
protected DeviceService createDeviceService ( ) {
2015-08-22 01:08:46 +02:00
return new GBDeviceService ( this ) ;
2015-08-21 00:58:18 +02:00
}
2015-05-13 23:15:20 +02:00
@Override
public void onCreate ( ) {
2017-04-27 07:52:11 +02:00
app = this ;
2015-05-13 23:15:20 +02:00
super . onCreate ( ) ;
2016-08-25 00:00:53 +02:00
if ( lockHandler ! = null ) {
// guard against multiple invocations (robolectric)
return ;
}
2015-09-25 00:53:40 +02:00
sharedPrefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
2016-04-25 23:18:55 +02:00
prefs = new Prefs ( sharedPrefs ) ;
2016-04-28 23:17:13 +02:00
gbPrefs = new GBPrefs ( prefs ) ;
2015-09-25 00:53:40 +02:00
2017-04-27 07:57:37 +02:00
if ( ! GBEnvironment . isEnvironmentSetup ( ) ) {
GBEnvironment . setupEnvironment ( GBEnvironment . createDeviceEnvironment ( ) ) ;
// setup db after the environment is set up, but don't do it in test mode
// in test mode, it's done individually, see TestBase
setupDatabase ( ) ;
}
2015-07-25 00:07:33 +02:00
// don't do anything here before we set up logging, otherwise
// slf4j may be implicitly initialized before we properly configured it.
2016-04-18 00:20:40 +02:00
setupLogging ( isFileLoggingEnabled ( ) ) ;
2015-10-07 23:32:58 +02:00
2019-05-20 21:53:53 +02:00
if ( getPrefsFileVersion ( ) ! = CURRENT_PREFS_VERSION ) {
2016-02-02 17:33:24 +01:00
migratePrefs ( getPrefsFileVersion ( ) ) ;
}
2015-10-07 23:32:58 +02:00
setupExceptionHandler ( ) ;
2015-06-05 21:46:56 +02:00
2016-06-18 23:35:34 +02:00
deviceManager = new DeviceManager ( this ) ;
2017-07-31 22:49:05 +02:00
String language = prefs . getString ( " language " , " default " ) ;
2017-07-31 23:00:02 +02:00
setLanguage ( language ) ;
2016-06-18 23:35:34 +02:00
2015-10-03 23:26:36 +02:00
deviceService = createDeviceService ( ) ;
2018-06-18 20:38:37 +02:00
loadAppsNotifBlackList ( ) ;
loadAppsPebbleBlackList ( ) ;
2017-08-18 10:30:19 +02:00
loadCalendarsBlackList ( ) ;
2015-12-07 23:33:32 +01:00
2016-05-19 23:58:13 +02:00
if ( isRunningMarshmallowOrLater ( ) ) {
2016-05-20 22:04:30 +02:00
notificationManager = ( NotificationManager ) context . getSystemService ( Context . NOTIFICATION_SERVICE ) ;
2017-04-19 13:23:13 +02:00
//the following will ensure the notification manager is kept alive
2019-06-05 16:00:18 +02:00
if ( isRunningOreoOrLater ( ) ) {
2018-02-14 21:27:24 +01:00
NotificationChannel channel = notificationManager . getNotificationChannel ( NOTIFICATION_CHANNEL_ID ) ;
2019-06-05 16:00:18 +02:00
if ( channel = = null ) {
2018-02-14 21:27:24 +01:00
channel = new NotificationChannel ( NOTIFICATION_CHANNEL_ID ,
getString ( R . string . notification_channel_name ) ,
NotificationManager . IMPORTANCE_LOW ) ;
notificationManager . createNotificationChannel ( channel ) ;
}
2018-05-16 19:03:06 +02:00
2020-07-28 01:09:59 +02:00
NotificationChannel channelHighPr = notificationManager . getNotificationChannel ( NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID ) ;
2020-03-03 18:01:39 +01:00
if ( channelHighPr = = null ) {
channelHighPr = new NotificationChannel ( NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID ,
getString ( R . string . notification_channel_high_priority_name ) ,
NotificationManager . IMPORTANCE_HIGH ) ;
notificationManager . createNotificationChannel ( channelHighPr ) ;
}
2018-05-16 19:03:06 +02:00
bluetoothStateChangeReceiver = new BluetoothStateChangeReceiver ( ) ;
registerReceiver ( bluetoothStateChangeReceiver , new IntentFilter ( BluetoothAdapter . ACTION_STATE_CHANGED ) ) ;
2018-02-14 21:27:24 +01:00
}
2020-07-28 01:09:59 +02:00
try {
startService ( new Intent ( this , NotificationCollectorMonitorService . class ) ) ;
} catch ( IllegalStateException e ) {
String message = e . toString ( ) ;
if ( message = = null ) {
message = getString ( R . string . _unknown_ ) ;
}
notificationManager . notify ( ERROR_IN_GADGETBRIDGE_NOTIFICATION ,
new NotificationCompat . Builder ( this , NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID )
. setSmallIcon ( R . drawable . gadgetbridge_img )
. setContentTitle ( getString ( R . string . error_background_service ) )
. setContentText ( getString ( R . string . error_background_service_reason_truncated ) )
. setStyle ( new NotificationCompat . BigTextStyle ( )
. bigText ( getString ( R . string . error_background_service_reason ) + " \" " + message + " \" " ) )
. setPriority ( NotificationCompat . PRIORITY_DEFAULT )
. build ( ) ) ;
}
2016-05-19 23:58:13 +02:00
}
2015-05-13 23:15:20 +02:00
}
2016-11-24 21:11:28 +01:00
@Override
public void onTrimMemory ( int level ) {
super . onTrimMemory ( level ) ;
if ( level > = TRIM_MEMORY_BACKGROUND ) {
if ( ! hasBusyDevice ( ) ) {
DBHelper . clearSession ( ) ;
}
}
}
/ * *
* Returns true if at least a single device is busy , e . g synchronizing activity data
* or something similar .
* Note : busy is not the same as connected or initialized !
* /
private boolean hasBusyDevice ( ) {
List < GBDevice > devices = getDeviceManager ( ) . getDevices ( ) ;
2016-12-07 23:13:51 +01:00
for ( GBDevice device : devices ) {
2016-11-24 21:11:28 +01:00
if ( device . isBusy ( ) ) {
return true ;
}
}
2016-11-25 14:53:12 +01:00
return false ;
2016-11-24 21:11:28 +01:00
}
2016-05-26 23:46:21 +02:00
public static void setupLogging ( boolean enabled ) {
logging . setupLogging ( enabled ) ;
}
2019-06-05 16:00:18 +02:00
public static String getLogPath ( ) {
2018-08-28 14:03:57 +02:00
return logging . getLogPath ( ) ;
}
2015-10-07 23:32:58 +02:00
private void setupExceptionHandler ( ) {
LoggingExceptionHandler handler = new LoggingExceptionHandler ( Thread . getDefaultUncaughtExceptionHandler ( ) ) ;
Thread . setDefaultUncaughtExceptionHandler ( handler ) ;
}
2015-05-23 00:45:12 +02:00
public static boolean isFileLoggingEnabled ( ) {
2016-04-25 23:18:55 +02:00
return prefs . getBoolean ( " log_to_file " , false ) ;
2015-05-23 00:45:12 +02:00
}
2017-01-08 15:51:56 +01:00
public static boolean minimizeNotification ( ) {
return prefs . getBoolean ( " minimize_priority " , false ) ;
}
2017-04-27 07:52:11 +02:00
public void setupDatabase ( ) {
DaoMaster . OpenHelper helper ;
GBEnvironment env = GBEnvironment . env ( ) ;
if ( env . isTest ( ) ) {
helper = new DaoMaster . DevOpenHelper ( this , null , null ) ;
} else {
helper = new DBOpenHelper ( this , DATABASE_NAME , null ) ;
}
2016-04-17 19:52:51 +02:00
SQLiteDatabase db = helper . getWritableDatabase ( ) ;
DaoMaster daoMaster = new DaoMaster ( db ) ;
2016-06-14 20:13:08 +02:00
if ( lockHandler = = null ) {
lockHandler = new LockHandler ( ) ;
}
lockHandler . init ( daoMaster , helper ) ;
2016-04-17 19:52:51 +02:00
}
2015-05-01 09:36:10 +02:00
public static Context getContext ( ) {
return context ;
}
2015-05-30 17:28:03 +02:00
2015-10-26 23:32:03 +01:00
/ * *
* Returns the facade for talking to devices . Devices are managed by
* an Android Service and this facade provides access to its functionality .
*
* @return the facade for talking to the service / devices .
* /
2015-08-21 00:58:18 +02:00
public static DeviceService deviceService ( ) {
return deviceService ;
}
2015-08-03 01:17:02 +02:00
/ * *
* Returns the DBHandler instance for reading / writing or throws GBException
* when that was not successful
* If acquiring was successful , callers must call # releaseDB when they
* are done ( from the same thread that acquired the lock !
2016-12-07 23:13:51 +01:00
* < p >
2016-06-14 20:13:08 +02:00
* Callers must not hold a reference to the returned instance because it
* will be invalidated at some point .
*
2015-08-03 01:17:02 +02:00
* @return the DBHandler
* @throws GBException
2015-09-24 14:45:21 +02:00
* @see # releaseDB ( )
2015-08-03 01:17:02 +02:00
* /
public static DBHandler acquireDB ( ) throws GBException {
try {
if ( dbLock . tryLock ( 30 , TimeUnit . SECONDS ) ) {
2016-05-16 23:00:04 +02:00
return lockHandler ;
2015-08-03 01:17:02 +02:00
}
} catch ( InterruptedException ex ) {
Log . i ( TAG , " Interrupted while waiting for DB lock " ) ;
}
throw new GBException ( " Unable to access the database. " ) ;
}
/ * *
* Releases the database lock .
2015-09-24 14:45:21 +02:00
*
2015-08-03 01:17:02 +02:00
* @throws IllegalMonitorStateException if the current thread is not owning the lock
* @see # acquireDB ( )
* /
public static void releaseDB ( ) {
dbLock . unlock ( ) ;
2015-05-30 17:28:03 +02:00
}
2016-04-14 16:44:44 +02:00
2015-06-06 00:10:38 +02:00
public static boolean isRunningLollipopOrLater ( ) {
return VERSION . SDK_INT > = Build . VERSION_CODES . LOLLIPOP ;
}
2015-09-25 00:53:40 +02:00
2016-05-19 16:34:59 +02:00
public static boolean isRunningMarshmallowOrLater ( ) {
return VERSION . SDK_INT > = Build . VERSION_CODES . M ;
}
2019-06-05 16:00:18 +02:00
2018-04-12 22:06:45 +02:00
public static boolean isRunningNougatOrLater ( ) {
return VERSION . SDK_INT > = Build . VERSION_CODES . N ;
}
2016-05-19 16:34:59 +02:00
2019-06-05 16:00:18 +02:00
public static boolean isRunningOreoOrLater ( ) {
2018-02-14 21:27:24 +01:00
return VERSION . SDK_INT > = Build . VERSION_CODES . O ;
}
2020-02-22 10:12:33 +01:00
public static boolean isRunningPieOrLater ( ) {
return VERSION . SDK_INT > = Build . VERSION_CODES . P ;
}
2016-05-19 23:58:13 +02:00
private static boolean isPrioritySender ( int prioritySenders , String number ) {
if ( prioritySenders = = Policy . PRIORITY_SENDERS_ANY ) {
return true ;
} else {
Uri uri = Uri . withAppendedPath ( PhoneLookup . CONTENT_FILTER_URI , Uri . encode ( number ) ) ;
String [ ] projection = new String [ ] { PhoneLookup . _ID , PhoneLookup . STARRED } ;
Cursor cursor = context . getContentResolver ( ) . query ( uri , projection , null , null , null ) ;
boolean exists = false ;
int starred = 0 ;
try {
2016-05-20 22:04:30 +02:00
if ( cursor ! = null & & cursor . moveToFirst ( ) ) {
2016-05-19 23:58:13 +02:00
exists = true ;
starred = cursor . getInt ( cursor . getColumnIndexOrThrow ( PhoneLookup . STARRED ) ) ;
}
} finally {
if ( cursor ! = null ) {
cursor . close ( ) ;
}
2016-05-19 16:34:59 +02:00
}
2016-05-19 23:58:13 +02:00
if ( prioritySenders = = Policy . PRIORITY_SENDERS_CONTACTS & & exists ) {
return true ;
} else if ( prioritySenders = = Policy . PRIORITY_SENDERS_STARRED & & starred = = 1 ) {
return true ;
2016-05-19 16:34:59 +02:00
}
2016-05-19 23:58:13 +02:00
return false ;
2016-05-19 16:34:59 +02:00
}
2016-05-19 23:58:13 +02:00
}
2016-05-20 21:49:25 +02:00
@TargetApi ( Build . VERSION_CODES . M )
2016-05-19 23:58:13 +02:00
public static boolean isPriorityNumber ( int priorityType , String number ) {
NotificationManager . Policy notificationPolicy = notificationManager . getNotificationPolicy ( ) ;
2016-12-07 23:13:51 +01:00
if ( priorityType = = Policy . PRIORITY_CATEGORY_MESSAGES ) {
2016-05-19 23:58:13 +02:00
if ( ( notificationPolicy . priorityCategories & Policy . PRIORITY_CATEGORY_MESSAGES ) = = Policy . PRIORITY_CATEGORY_MESSAGES ) {
return isPrioritySender ( notificationPolicy . priorityMessageSenders , number ) ;
}
} else if ( priorityType = = Policy . PRIORITY_CATEGORY_CALLS ) {
if ( ( notificationPolicy . priorityCategories & Policy . PRIORITY_CATEGORY_CALLS ) = = Policy . PRIORITY_CATEGORY_CALLS ) {
return isPrioritySender ( notificationPolicy . priorityCallSenders , number ) ;
}
2016-05-19 16:34:59 +02:00
}
return false ;
}
2016-05-20 21:49:25 +02:00
@TargetApi ( Build . VERSION_CODES . M )
2016-05-19 23:58:13 +02:00
public static int getGrantedInterruptionFilter ( ) {
if ( prefs . getBoolean ( " notification_filter " , false ) & & GBApplication . isRunningMarshmallowOrLater ( ) ) {
if ( notificationManager . isNotificationPolicyAccessGranted ( ) ) {
return notificationManager . getCurrentInterruptionFilter ( ) ;
}
}
return NotificationManager . INTERRUPTION_FILTER_ALL ;
}
2018-06-18 20:38:37 +02:00
private static HashSet < String > apps_notification_blacklist = null ;
2017-04-22 16:59:55 +02:00
2018-06-18 20:38:37 +02:00
public static boolean appIsNotifBlacklisted ( String packageName ) {
if ( apps_notification_blacklist = = null ) {
GB . log ( " appIsNotifBlacklisted: apps_notification_blacklist is null! " , GB . INFO , null ) ;
2017-05-21 21:02:23 +02:00
}
2018-06-18 20:38:37 +02:00
return apps_notification_blacklist ! = null & & apps_notification_blacklist . contains ( packageName ) ;
2017-04-22 16:59:55 +02:00
}
2018-06-18 20:38:37 +02:00
public static void setAppsNotifBlackList ( Set < String > packageNames ) {
2017-04-22 16:59:55 +02:00
if ( packageNames = = null ) {
2018-06-18 20:38:37 +02:00
GB . log ( " Set null apps_notification_blacklist " , GB . INFO , null ) ;
apps_notification_blacklist = new HashSet < > ( ) ;
2017-04-22 16:59:55 +02:00
} else {
2018-06-18 20:38:37 +02:00
apps_notification_blacklist = new HashSet < > ( packageNames ) ;
2017-04-22 16:59:55 +02:00
}
2018-06-18 20:38:37 +02:00
GB . log ( " New apps_notification_blacklist has " + apps_notification_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
saveAppsNotifBlackList ( ) ;
2017-04-22 16:59:55 +02:00
}
2015-09-25 00:53:40 +02:00
2018-06-18 20:38:37 +02:00
private static void loadAppsNotifBlackList ( ) {
GB . log ( " Loading apps_notification_blacklist " , GB . INFO , null ) ;
2019-02-28 21:57:45 +01:00
apps_notification_blacklist = ( HashSet < String > ) sharedPrefs . getStringSet ( GBPrefs . PACKAGE_BLACKLIST , null ) ; // lgtm [java/abstract-to-concrete-cast]
2018-06-18 20:38:37 +02:00
if ( apps_notification_blacklist = = null ) {
apps_notification_blacklist = new HashSet < > ( ) ;
2015-09-25 00:53:40 +02:00
}
2018-06-18 20:38:37 +02:00
GB . log ( " Loaded apps_notification_blacklist has " + apps_notification_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
2015-09-25 00:53:40 +02:00
}
2018-06-18 20:38:37 +02:00
private static void saveAppsNotifBlackList ( ) {
GB . log ( " Saving apps_notification_blacklist with " + apps_notification_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
2015-09-25 00:53:40 +02:00
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
2018-06-18 20:38:37 +02:00
if ( apps_notification_blacklist . isEmpty ( ) ) {
2017-04-22 16:59:55 +02:00
editor . putStringSet ( GBPrefs . PACKAGE_BLACKLIST , null ) ;
2015-09-25 00:53:40 +02:00
} else {
2018-06-18 20:38:37 +02:00
Prefs . putStringSet ( editor , GBPrefs . PACKAGE_BLACKLIST , apps_notification_blacklist ) ;
2015-09-25 00:53:40 +02:00
}
editor . apply ( ) ;
}
2018-06-18 20:38:37 +02:00
public static void addAppToNotifBlacklist ( String packageName ) {
if ( apps_notification_blacklist . add ( packageName ) ) {
saveAppsNotifBlackList ( ) ;
2015-09-25 00:53:40 +02:00
}
}
2018-06-18 20:38:37 +02:00
public static synchronized void removeFromAppsNotifBlacklist ( String packageName ) {
GB . log ( " Removing from apps_notification_blacklist: " + packageName , GB . INFO , null ) ;
apps_notification_blacklist . remove ( packageName ) ;
saveAppsNotifBlackList ( ) ;
2017-08-18 10:30:19 +02:00
}
2018-06-18 20:38:37 +02:00
private static HashSet < String > apps_pebblemsg_blacklist = null ;
public static boolean appIsPebbleBlacklisted ( String sender ) {
if ( apps_pebblemsg_blacklist = = null ) {
GB . log ( " appIsPebbleBlacklisted: apps_pebblemsg_blacklist is null! " , GB . INFO , null ) ;
}
return apps_pebblemsg_blacklist ! = null & & apps_pebblemsg_blacklist . contains ( sender ) ;
}
public static void setAppsPebbleBlackList ( Set < String > packageNames ) {
if ( packageNames = = null ) {
GB . log ( " Set null apps_pebblemsg_blacklist " , GB . INFO , null ) ;
apps_pebblemsg_blacklist = new HashSet < > ( ) ;
} else {
apps_pebblemsg_blacklist = new HashSet < > ( packageNames ) ;
}
GB . log ( " New apps_pebblemsg_blacklist has " + apps_pebblemsg_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
saveAppsPebbleBlackList ( ) ;
}
private static void loadAppsPebbleBlackList ( ) {
GB . log ( " Loading apps_pebblemsg_blacklist " , GB . INFO , null ) ;
2019-02-28 21:57:45 +01:00
apps_pebblemsg_blacklist = ( HashSet < String > ) sharedPrefs . getStringSet ( GBPrefs . PACKAGE_PEBBLEMSG_BLACKLIST , null ) ; // lgtm [java/abstract-to-concrete-cast]
2018-06-18 20:38:37 +02:00
if ( apps_pebblemsg_blacklist = = null ) {
apps_pebblemsg_blacklist = new HashSet < > ( ) ;
}
GB . log ( " Loaded apps_pebblemsg_blacklist has " + apps_pebblemsg_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
}
private static void saveAppsPebbleBlackList ( ) {
GB . log ( " Saving apps_pebblemsg_blacklist with " + apps_pebblemsg_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
if ( apps_pebblemsg_blacklist . isEmpty ( ) ) {
editor . putStringSet ( GBPrefs . PACKAGE_PEBBLEMSG_BLACKLIST , null ) ;
} else {
Prefs . putStringSet ( editor , GBPrefs . PACKAGE_PEBBLEMSG_BLACKLIST , apps_pebblemsg_blacklist ) ;
}
editor . apply ( ) ;
}
public static void addAppToPebbleBlacklist ( String packageName ) {
if ( apps_pebblemsg_blacklist . add ( packageNameToPebbleMsgSender ( packageName ) ) ) {
saveAppsPebbleBlackList ( ) ;
}
}
public static synchronized void removeFromAppsPebbleBlacklist ( String packageName ) {
GB . log ( " Removing from apps_pebblemsg_blacklist: " + packageName , GB . INFO , null ) ;
apps_pebblemsg_blacklist . remove ( packageNameToPebbleMsgSender ( packageName ) ) ;
saveAppsPebbleBlackList ( ) ;
}
2019-06-05 16:00:18 +02:00
public static String packageNameToPebbleMsgSender ( String packageName ) {
if ( " eu.siacs.conversations " . equals ( packageName ) ) {
return ( " Conversations " ) ;
} else if ( " net.osmand.plus " . equals ( packageName ) ) {
return ( " OsmAnd " ) ;
}
return packageName ;
2018-06-18 20:38:37 +02:00
}
2017-08-18 10:30:19 +02:00
private static HashSet < String > calendars_blacklist = null ;
public static boolean calendarIsBlacklisted ( String calendarDisplayName ) {
if ( calendars_blacklist = = null ) {
GB . log ( " calendarIsBlacklisted: calendars_blacklist is null! " , GB . INFO , null ) ;
}
return calendars_blacklist ! = null & & calendars_blacklist . contains ( calendarDisplayName ) ;
}
public static void setCalendarsBlackList ( Set < String > calendarNames ) {
if ( calendarNames = = null ) {
2018-06-18 20:38:37 +02:00
GB . log ( " Set null apps_notification_blacklist " , GB . INFO , null ) ;
2017-08-18 10:30:19 +02:00
calendars_blacklist = new HashSet < > ( ) ;
} else {
calendars_blacklist = new HashSet < > ( calendarNames ) ;
}
GB . log ( " New calendars_blacklist has " + calendars_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
saveCalendarsBlackList ( ) ;
}
public static void addCalendarToBlacklist ( String calendarDisplayName ) {
if ( calendars_blacklist . add ( calendarDisplayName ) ) {
saveCalendarsBlackList ( ) ;
}
}
public static void removeFromCalendarBlacklist ( String calendarDisplayName ) {
calendars_blacklist . remove ( calendarDisplayName ) ;
saveCalendarsBlackList ( ) ;
}
private static void loadCalendarsBlackList ( ) {
GB . log ( " Loading calendars_blacklist " , GB . INFO , null ) ;
2019-02-28 21:57:45 +01:00
calendars_blacklist = ( HashSet < String > ) sharedPrefs . getStringSet ( GBPrefs . CALENDAR_BLACKLIST , null ) ; // lgtm [java/abstract-to-concrete-cast]
2017-08-18 10:30:19 +02:00
if ( calendars_blacklist = = null ) {
calendars_blacklist = new HashSet < > ( ) ;
}
GB . log ( " Loaded calendars_blacklist has " + calendars_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
}
private static void saveCalendarsBlackList ( ) {
GB . log ( " Saving calendars_blacklist with " + calendars_blacklist . size ( ) + " entries " , GB . INFO , null ) ;
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
if ( calendars_blacklist . isEmpty ( ) ) {
editor . putStringSet ( GBPrefs . CALENDAR_BLACKLIST , null ) ;
} else {
Prefs . putStringSet ( editor , GBPrefs . CALENDAR_BLACKLIST , calendars_blacklist ) ;
}
editor . apply ( ) ;
2015-09-25 00:53:40 +02:00
}
2015-12-08 23:42:58 +01:00
/ * *
2016-08-31 17:35:28 +02:00
* Deletes both the old Activity database and the new one recreates it with empty tables .
2015-12-14 23:31:31 +01:00
*
2015-12-08 23:42:58 +01:00
* @return true on successful deletion
* /
2016-08-27 22:55:00 +02:00
public static synchronized boolean deleteActivityDatabase ( Context context ) {
2016-05-13 23:47:47 +02:00
// TODO: flush, close, reopen db
2016-05-17 00:51:00 +02:00
if ( lockHandler ! = null ) {
lockHandler . closeDb ( ) ;
}
2017-02-23 22:44:44 +01:00
boolean result = deleteOldActivityDatabase ( context ) ;
2016-08-27 22:51:00 +02:00
result & = getContext ( ) . deleteDatabase ( DATABASE_NAME ) ;
2015-12-08 23:42:58 +01:00
return result ;
}
2015-12-14 23:31:31 +01:00
2016-08-31 17:35:28 +02:00
/ * *
* Deletes the legacy ( pre 0 . 12 ) Activity database
*
* @return true on successful deletion
* /
public static synchronized boolean deleteOldActivityDatabase ( Context context ) {
DBHelper dbHelper = new DBHelper ( context ) ;
boolean result = true ;
2017-02-23 22:44:44 +01:00
if ( dbHelper . existsDB ( " ActivityDatabase " ) ) {
result = getContext ( ) . deleteDatabase ( " ActivityDatabase " ) ;
2016-08-31 17:35:28 +02:00
}
return result ;
}
2016-02-02 17:33:24 +01:00
private int getPrefsFileVersion ( ) {
2016-02-21 13:04:32 +01:00
try {
return Integer . parseInt ( sharedPrefs . getString ( PREFS_VERSION , " 0 " ) ) ; //0 is legacy
} catch ( Exception e ) {
//in version 1 this was an int
return 1 ;
}
2016-02-02 17:33:24 +01:00
}
2019-11-24 18:40:44 +01:00
private void migrateStringPrefToPerDevicePref ( String globalPref , String globalPrefDefault , String perDevicePref , ArrayList < DeviceType > deviceTypes ) {
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
String globalPrefValue = prefs . getString ( globalPref , globalPrefDefault ) ;
try ( DBHandler db = acquireDB ( ) ) {
DaoSession daoSession = db . getDaoSession ( ) ;
List < Device > activeDevices = DBHelper . getActiveDevices ( daoSession ) ;
for ( Device dbDevice : activeDevices ) {
SharedPreferences deviceSpecificSharedPrefs = GBApplication . getDeviceSpecificSharedPrefs ( dbDevice . getIdentifier ( ) ) ;
if ( deviceSpecificSharedPrefs ! = null ) {
SharedPreferences . Editor deviceSharedPrefsEdit = deviceSpecificSharedPrefs . edit ( ) ;
DeviceType deviceType = fromKey ( dbDevice . getType ( ) ) ;
if ( deviceTypes . contains ( deviceType ) ) {
Log . i ( TAG , " migrating global string preference " + globalPref + " for " + deviceType . name ( ) + " " + dbDevice . getIdentifier ( ) ) ;
deviceSharedPrefsEdit . putString ( perDevicePref , globalPrefValue ) ;
}
deviceSharedPrefsEdit . apply ( ) ;
}
}
editor . remove ( globalPref ) ;
editor . apply ( ) ;
} catch ( Exception e ) {
Log . w ( TAG , " error acquiring DB lock " ) ;
}
}
private void migrateBooleanPrefToPerDevicePref ( String globalPref , Boolean globalPrefDefault , String perDevicePref , ArrayList < DeviceType > deviceTypes ) {
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
boolean globalPrefValue = prefs . getBoolean ( globalPref , globalPrefDefault ) ;
try ( DBHandler db = acquireDB ( ) ) {
DaoSession daoSession = db . getDaoSession ( ) ;
List < Device > activeDevices = DBHelper . getActiveDevices ( daoSession ) ;
for ( Device dbDevice : activeDevices ) {
SharedPreferences deviceSpecificSharedPrefs = GBApplication . getDeviceSpecificSharedPrefs ( dbDevice . getIdentifier ( ) ) ;
if ( deviceSpecificSharedPrefs ! = null ) {
SharedPreferences . Editor deviceSharedPrefsEdit = deviceSpecificSharedPrefs . edit ( ) ;
DeviceType deviceType = fromKey ( dbDevice . getType ( ) ) ;
if ( deviceTypes . contains ( deviceType ) ) {
Log . i ( TAG , " migrating global boolean preference " + globalPref + " for " + deviceType . name ( ) + " " + dbDevice . getIdentifier ( ) ) ;
deviceSharedPrefsEdit . putBoolean ( perDevicePref , globalPrefValue ) ;
}
deviceSharedPrefsEdit . apply ( ) ;
}
}
editor . remove ( globalPref ) ;
editor . apply ( ) ;
} catch ( Exception e ) {
Log . w ( TAG , " error acquiring DB lock " ) ;
}
}
2016-02-02 17:33:24 +01:00
private void migratePrefs ( int oldVersion ) {
2016-02-21 13:04:32 +01:00
SharedPreferences . Editor editor = sharedPrefs . edit ( ) ;
2019-05-20 16:36:06 +02:00
if ( oldVersion = = 0 ) {
String legacyGender = sharedPrefs . getString ( " mi_user_gender " , null ) ;
String legacyHeight = sharedPrefs . getString ( " mi_user_height_cm " , null ) ;
String legacyWeight = sharedPrefs . getString ( " mi_user_weight_kg " , null ) ;
String legacyYOB = sharedPrefs . getString ( " mi_user_year_of_birth " , null ) ;
if ( legacyGender ! = null ) {
int gender = " male " . equals ( legacyGender ) ? 1 : " female " . equals ( legacyGender ) ? 0 : 2 ;
editor . putString ( ActivityUser . PREF_USER_GENDER , Integer . toString ( gender ) ) ;
editor . remove ( " mi_user_gender " ) ;
}
if ( legacyHeight ! = null ) {
editor . putString ( ActivityUser . PREF_USER_HEIGHT_CM , legacyHeight ) ;
editor . remove ( " mi_user_height_cm " ) ;
}
if ( legacyWeight ! = null ) {
editor . putString ( ActivityUser . PREF_USER_WEIGHT_KG , legacyWeight ) ;
editor . remove ( " mi_user_weight_kg " ) ;
}
if ( legacyYOB ! = null ) {
editor . putString ( ActivityUser . PREF_USER_YEAR_OF_BIRTH , legacyYOB ) ;
editor . remove ( " mi_user_year_of_birth " ) ;
}
}
if ( oldVersion < 2 ) {
//migrate the integer version of gender introduced in version 1 to a string value, needed for the way Android accesses the shared preferences
int legacyGender_1 = 2 ;
try {
legacyGender_1 = sharedPrefs . getInt ( ActivityUser . PREF_USER_GENDER , 2 ) ;
} catch ( Exception e ) {
Log . e ( TAG , " Could not access legacy activity gender " , e ) ;
}
editor . putString ( ActivityUser . PREF_USER_GENDER , Integer . toString ( legacyGender_1 ) ) ;
}
if ( oldVersion < 3 ) {
2019-05-20 21:53:53 +02:00
try ( DBHandler db = acquireDB ( ) ) {
DaoSession daoSession = db . getDaoSession ( ) ;
List < Device > activeDevices = DBHelper . getActiveDevices ( daoSession ) ;
for ( Device dbDevice : activeDevices ) {
2019-09-19 23:18:17 +02:00
SharedPreferences deviceSpecificSharedPrefs = GBApplication . getDeviceSpecificSharedPrefs ( dbDevice . getIdentifier ( ) ) ;
if ( deviceSpecificSharedPrefs ! = null ) {
SharedPreferences . Editor deviceSharedPrefsEdit = deviceSpecificSharedPrefs . edit ( ) ;
2019-05-20 21:53:53 +02:00
String preferenceKey = dbDevice . getIdentifier ( ) + " _lastSportsActivityTimeMillis " ;
long lastSportsActivityTimeMillis = sharedPrefs . getLong ( preferenceKey , 0 ) ;
if ( lastSportsActivityTimeMillis ! = 0 ) {
deviceSharedPrefsEdit . putLong ( " lastSportsActivityTimeMillis " , lastSportsActivityTimeMillis ) ;
editor . remove ( preferenceKey ) ;
}
preferenceKey = dbDevice . getIdentifier ( ) + " _lastSyncTimeMillis " ;
long lastSyncTimeMillis = sharedPrefs . getLong ( preferenceKey , 0 ) ;
if ( lastSyncTimeMillis ! = 0 ) {
deviceSharedPrefsEdit . putLong ( " lastSyncTimeMillis " , lastSyncTimeMillis ) ;
editor . remove ( preferenceKey ) ;
}
2019-05-23 23:24:49 +02:00
String newLanguage = null ;
Set < String > displayItems = null ;
DeviceType deviceType = fromKey ( dbDevice . getType ( ) ) ;
if ( deviceType = = AMAZFITBIP | | deviceType = = AMAZFITCOR | | deviceType = = AMAZFITCOR2 ) {
int oldLanguage = prefs . getInt ( " amazfitbip_language " , - 1 ) ;
newLanguage = " auto " ;
String [ ] oldLanguageLookup = { " zh_CN " , " zh_TW " , " en_US " , " es_ES " , " ru_RU " , " de_DE " , " it_IT " , " fr_FR " , " tr_TR " } ;
if ( oldLanguage > = 0 & & oldLanguage < oldLanguageLookup . length ) {
newLanguage = oldLanguageLookup [ oldLanguage ] ;
}
}
if ( deviceType = = AMAZFITBIP | | deviceType = = AMAZFITCOR ) {
deviceSharedPrefsEdit . putString ( " disconnect_notification " , prefs . getString ( " disconnect_notification " , " off " ) ) ;
deviceSharedPrefsEdit . putString ( " disconnect_notification_start " , prefs . getString ( " disconnect_notification_start " , " 8:00 " ) ) ;
deviceSharedPrefsEdit . putString ( " disconnect_notification_end " , prefs . getString ( " disconnect_notification_end " , " 22:00 " ) ) ;
}
2019-05-24 23:46:20 +02:00
if ( deviceType = = MIBAND2 | | deviceType = = MIBAND3 ) {
2019-06-05 12:48:33 +02:00
deviceSharedPrefsEdit . putString ( " do_not_disturb " , prefs . getString ( " mi2_do_not_disturb " , " off " ) ) ;
deviceSharedPrefsEdit . putString ( " do_not_disturb_start " , prefs . getString ( " mi2_do_not_disturb_start " , " 1:00 " ) ) ;
deviceSharedPrefsEdit . putString ( " do_not_disturb_end " , prefs . getString ( " mi2_do_not_disturb_end " , " 6:00 " ) ) ;
2019-05-24 23:46:20 +02:00
}
2019-06-05 16:00:18 +02:00
if ( dbDevice . getManufacturer ( ) . equals ( " Huami " ) ) {
deviceSharedPrefsEdit . putString ( " activate_display_on_lift_wrist " , prefs . getString ( " activate_display_on_lift_wrist " , " off " ) ) ;
deviceSharedPrefsEdit . putString ( " display_on_lift_start " , prefs . getString ( " display_on_lift_start " , " 0:00 " ) ) ;
deviceSharedPrefsEdit . putString ( " display_on_lift_end " , prefs . getString ( " display_on_lift_end " , " 0:00 " ) ) ;
}
2019-05-23 23:24:49 +02:00
switch ( deviceType ) {
2019-06-05 12:48:33 +02:00
case MIBAND :
deviceSharedPrefsEdit . putBoolean ( " low_latency_fw_update " , prefs . getBoolean ( " mi_low_latency_fw_update " , true ) ) ;
2019-11-24 18:40:44 +01:00
deviceSharedPrefsEdit . putString ( " device_time_offset_hours " , String . valueOf ( prefs . getInt ( " mi_device_time_offset_hours " , 0 ) ) ) ;
2019-06-05 12:48:33 +02:00
break ;
2019-05-20 21:53:53 +02:00
case AMAZFITCOR :
2019-05-23 23:24:49 +02:00
displayItems = prefs . getStringSet ( " cor_display_items " , null ) ;
break ;
2019-05-20 21:53:53 +02:00
case AMAZFITBIP :
2019-05-23 23:24:49 +02:00
displayItems = prefs . getStringSet ( " bip_display_items " , null ) ;
break ;
case MIBAND2 :
displayItems = prefs . getStringSet ( " mi2_display_items " , null ) ;
deviceSharedPrefsEdit . putBoolean ( " mi2_enable_text_notifications " , prefs . getBoolean ( " mi2_enable_text_notifications " , true ) ) ;
deviceSharedPrefsEdit . putString ( " mi2_dateformat " , prefs . getString ( " mi2_dateformat " , " dateformat_time " ) ) ;
2019-06-05 16:00:18 +02:00
deviceSharedPrefsEdit . putBoolean ( " rotate_wrist_to_cycle_info " , prefs . getBoolean ( " mi2_rotate_wrist_to_switch_info " , false ) ) ;
2019-05-20 21:53:53 +02:00
break ;
case MIBAND3 :
2019-05-23 23:24:49 +02:00
newLanguage = prefs . getString ( " miband3_language " , " auto " ) ;
displayItems = prefs . getStringSet ( " miband3_display_items " , null ) ;
deviceSharedPrefsEdit . putBoolean ( " swipe_unlock " , prefs . getBoolean ( " mi3_band_screen_unlock " , false ) ) ;
deviceSharedPrefsEdit . putString ( " night_mode " , prefs . getString ( " mi3_night_mode " , " off " ) ) ;
deviceSharedPrefsEdit . putString ( " night_mode_start " , prefs . getString ( " mi3_night_mode_start " , " 16:00 " ) ) ;
deviceSharedPrefsEdit . putString ( " night_mode_end " , prefs . getString ( " mi3_night_mode_end " , " 7:00 " ) ) ;
}
if ( displayItems ! = null ) {
deviceSharedPrefsEdit . putStringSet ( " display_items " , displayItems ) ;
}
if ( newLanguage ! = null ) {
deviceSharedPrefsEdit . putString ( " language " , newLanguage ) ;
2019-05-20 21:53:53 +02:00
}
2019-09-19 23:18:17 +02:00
deviceSharedPrefsEdit . apply ( ) ;
2019-05-20 16:36:06 +02:00
}
2019-05-20 21:53:53 +02:00
}
editor . remove ( " amazfitbip_language " ) ;
2019-05-23 23:24:49 +02:00
editor . remove ( " bip_display_items " ) ;
editor . remove ( " cor_display_items " ) ;
editor . remove ( " disconnect_notification " ) ;
editor . remove ( " disconnect_notification_start " ) ;
editor . remove ( " disconnect_notification_end " ) ;
2019-06-05 16:00:18 +02:00
editor . remove ( " activate_display_on_lift_wrist " ) ;
editor . remove ( " display_on_lift_start " ) ;
editor . remove ( " display_on_lift_end " ) ;
2019-06-05 12:48:33 +02:00
editor . remove ( " mi_low_latency_fw_update " ) ;
2019-06-05 14:11:44 +02:00
editor . remove ( " mi_device_time_offset_hours " ) ;
2019-05-24 23:46:20 +02:00
editor . remove ( " mi2_do_not_disturb " ) ;
editor . remove ( " mi2_do_not_disturb_start " ) ;
editor . remove ( " mi2_do_not_disturb_end " ) ;
2019-05-23 23:24:49 +02:00
editor . remove ( " mi2_dateformat " ) ;
editor . remove ( " mi2_display_items " ) ;
2019-06-05 16:00:18 +02:00
editor . remove ( " mi2_rotate_wrist_to_switch_info " ) ;
2019-05-23 23:24:49 +02:00
editor . remove ( " mi2_enable_text_notifications " ) ;
editor . remove ( " mi3_band_screen_unlock " ) ;
editor . remove ( " mi3_night_mode " ) ;
editor . remove ( " mi3_night_mode_start " ) ;
editor . remove ( " mi3_night_mode_end " ) ;
editor . remove ( " miband3_language " ) ;
2019-05-20 21:53:53 +02:00
} catch ( Exception e ) {
Log . w ( TAG , " error acquiring DB lock " ) ;
2019-05-20 16:36:06 +02:00
}
2016-02-02 17:33:24 +01:00
}
2019-06-18 22:07:43 +02:00
if ( oldVersion < 4 ) {
try ( DBHandler db = acquireDB ( ) ) {
DaoSession daoSession = db . getDaoSession ( ) ;
List < Device > activeDevices = DBHelper . getActiveDevices ( daoSession ) ;
for ( Device dbDevice : activeDevices ) {
SharedPreferences deviceSharedPrefs = GBApplication . getDeviceSpecificSharedPrefs ( dbDevice . getIdentifier ( ) ) ;
SharedPreferences . Editor deviceSharedPrefsEdit = deviceSharedPrefs . edit ( ) ;
DeviceType deviceType = fromKey ( dbDevice . getType ( ) ) ;
if ( deviceType = = MIBAND ) {
int deviceTimeOffsetHours = deviceSharedPrefs . getInt ( " device_time_offset_hours " , 0 ) ;
deviceSharedPrefsEdit . putString ( " device_time_offset_hours " , Integer . toString ( deviceTimeOffsetHours ) ) ;
}
deviceSharedPrefsEdit . apply ( ) ;
}
} catch ( Exception e ) {
Log . w ( TAG , " error acquiring DB lock " ) ;
}
}
2019-10-05 22:35:30 +02:00
if ( oldVersion < 5 ) {
try ( DBHandler db = acquireDB ( ) ) {
DaoSession daoSession = db . getDaoSession ( ) ;
List < Device > activeDevices = DBHelper . getActiveDevices ( daoSession ) ;
for ( Device dbDevice : activeDevices ) {
SharedPreferences deviceSpecificSharedPrefs = GBApplication . getDeviceSpecificSharedPrefs ( dbDevice . getIdentifier ( ) ) ;
if ( deviceSpecificSharedPrefs ! = null ) {
SharedPreferences . Editor deviceSharedPrefsEdit = deviceSpecificSharedPrefs . edit ( ) ;
DeviceType deviceType = fromKey ( dbDevice . getType ( ) ) ;
String newWearside = null ;
String newOrientation = null ;
String newTimeformat = null ;
switch ( deviceType ) {
case AMAZFITBIP :
case AMAZFITCOR :
case AMAZFITCOR2 :
case MIBAND :
case MIBAND2 :
case MIBAND3 :
case MIBAND4 :
newWearside = prefs . getString ( " mi_wearside " , " left " ) ;
break ;
2020-07-28 18:16:56 +02:00
case MIBAND5 :
newWearside = prefs . getString ( " mi_wearside " , " left " ) ;
break ;
2019-10-05 22:35:30 +02:00
case HPLUS :
newWearside = prefs . getString ( " hplus_wrist " , " left " ) ;
newTimeformat = prefs . getString ( " hplus_timeformat " , " 24h " ) ;
break ;
case ID115 :
newWearside = prefs . getString ( " id115_wrist " , " left " ) ;
newOrientation = prefs . getString ( " id115_screen_orientation " , " horizontal " ) ;
break ;
case ZETIME :
newWearside = prefs . getString ( " zetime_wrist " , " left " ) ;
newTimeformat = prefs . getInt ( " zetime_timeformat " , 1 ) = = 2 ? " am/pm " : " 24h " ;
break ;
}
if ( newWearside ! = null ) {
deviceSharedPrefsEdit . putString ( " wearlocation " , newWearside ) ;
}
if ( newOrientation ! = null ) {
deviceSharedPrefsEdit . putString ( " screen_orientation " , newOrientation ) ;
}
if ( newTimeformat ! = null ) {
deviceSharedPrefsEdit . putString ( " timeformat " , newTimeformat ) ;
}
deviceSharedPrefsEdit . apply ( ) ;
}
}
editor . remove ( " hplus_timeformat " ) ;
editor . remove ( " hplus_wrist " ) ;
editor . remove ( " id115_wrist " ) ;
editor . remove ( " id115_screen_orientation " ) ;
editor . remove ( " mi_wearside " ) ;
editor . remove ( " zetime_timeformat " ) ;
editor . remove ( " zetime_wrist " ) ;
} catch ( Exception e ) {
Log . w ( TAG , " error acquiring DB lock " ) ;
}
}
2019-11-24 18:40:44 +01:00
if ( oldVersion < 6 ) {
migrateBooleanPrefToPerDevicePref ( " mi2_enable_button_action " , false , " button_action_enable " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
migrateBooleanPrefToPerDevicePref ( " mi2_button_action_vibrate " , false , " button_action_vibrate " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
migrateStringPrefToPerDevicePref ( " mi_button_press_count " , " 6 " , " button_action_press_count " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
migrateStringPrefToPerDevicePref ( " mi_button_press_count_max_delay " , " 2000 " , " button_action_press_max_interval " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
migrateStringPrefToPerDevicePref ( " mi_button_press_count_match_delay " , " 0 " , " button_action_broadcast_delay " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
migrateStringPrefToPerDevicePref ( " mi_button_press_broadcast " , " nodomain.freeyourgadget.gadgetbridge.ButtonPressed " , " button_action_broadcast " , new ArrayList < > ( Collections . singletonList ( MIBAND2 ) ) ) ;
}
2019-12-14 23:43:54 +01:00
if ( oldVersion < 7 ) {
migrateStringPrefToPerDevicePref ( " mi_reserve_alarm_calendar " , " 0 " , " reserve_alarms_calendar " , new ArrayList < > ( Arrays . asList ( MIBAND , MIBAND2 ) ) ) ;
}
2019-10-05 22:35:30 +02:00
2019-05-20 16:36:06 +02:00
editor . putString ( PREFS_VERSION , Integer . toString ( CURRENT_PREFS_VERSION ) ) ;
2016-04-14 16:15:58 +02:00
editor . apply ( ) ;
2016-02-02 17:33:24 +01:00
}
2019-05-09 14:55:37 +02:00
public static SharedPreferences getDeviceSpecificSharedPrefs ( String deviceIdentifier ) {
if ( deviceIdentifier = = null | | deviceIdentifier . isEmpty ( ) ) {
return null ;
}
return context . getSharedPreferences ( " devicesettings_ " + deviceIdentifier , Context . MODE_PRIVATE ) ;
}
2017-07-31 23:00:02 +02:00
public static void setLanguage ( String lang ) {
2017-07-31 22:49:05 +02:00
if ( lang . equals ( " default " ) ) {
2017-07-31 23:00:02 +02:00
language = Resources . getSystem ( ) . getConfiguration ( ) . locale ;
2017-07-31 22:49:05 +02:00
} else {
language = new Locale ( lang ) ;
}
2017-09-03 01:02:31 +02:00
updateLanguage ( language ) ;
}
2017-07-31 22:49:05 +02:00
2017-09-03 01:02:31 +02:00
public static void updateLanguage ( Locale locale ) {
AndroidUtils . setLanguage ( context , locale ) ;
2017-07-31 23:00:02 +02:00
2017-07-31 22:49:05 +02:00
Intent intent = new Intent ( ) ;
intent . setAction ( ACTION_LANGUAGE_CHANGE ) ;
LocalBroadcastManager . getInstance ( context ) . sendBroadcast ( intent ) ;
}
2016-01-09 16:07:22 +01:00
public static LimitedQueue getIDSenderLookup ( ) {
2015-12-14 23:31:31 +01:00
return mIDSenderLookup ;
}
2016-04-14 15:21:25 +02:00
public static boolean isDarkThemeEnabled ( ) {
2020-05-05 14:46:09 +02:00
String selectedTheme = prefs . getString ( " pref_key_theme " , context . getString ( R . string . pref_theme_value_system ) ) ;
2020-04-13 17:51:36 +02:00
UiModeManager umm = ( UiModeManager ) context . getSystemService ( Context . UI_MODE_SERVICE ) ;
return selectedTheme . equals ( context . getString ( R . string . pref_theme_value_dark ) ) | |
( selectedTheme . equals ( context . getString ( R . string . pref_theme_value_system ) )
& & ( umm . getNightMode ( ) = = UiModeManager . MODE_NIGHT_YES ) ) ;
2016-04-14 15:21:25 +02:00
}
2016-04-23 23:24:56 +02:00
public static int getTextColor ( Context context ) {
TypedValue typedValue = new TypedValue ( ) ;
Resources . Theme theme = context . getTheme ( ) ;
2017-04-08 15:49:00 +02:00
theme . resolveAttribute ( R . attr . textColorPrimary , typedValue , true ) ;
2016-04-23 23:24:56 +02:00
return typedValue . data ;
}
2016-12-07 23:13:51 +01:00
2017-09-03 01:02:31 +02:00
@Override
public void onConfigurationChanged ( Configuration newConfig ) {
super . onConfigurationChanged ( newConfig ) ;
updateLanguage ( getLanguage ( ) ) ;
}
2016-04-23 23:24:56 +02:00
public static int getBackgroundColor ( Context context ) {
TypedValue typedValue = new TypedValue ( ) ;
Resources . Theme theme = context . getTheme ( ) ;
theme . resolveAttribute ( android . R . attr . background , typedValue , true ) ;
return typedValue . data ;
}
2016-04-25 23:18:55 +02:00
public static Prefs getPrefs ( ) {
return prefs ;
}
2016-04-28 23:17:13 +02:00
public static GBPrefs getGBPrefs ( ) {
return gbPrefs ;
2016-04-14 15:21:25 +02:00
}
2016-06-18 23:35:34 +02:00
2016-12-07 23:13:51 +01:00
public DeviceManager getDeviceManager ( ) {
2016-06-18 23:35:34 +02:00
return deviceManager ;
}
2017-04-27 07:52:11 +02:00
public static GBApplication app ( ) {
return app ;
}
2017-07-31 22:49:05 +02:00
public static Locale getLanguage ( ) {
return language ;
}
2017-10-19 21:52:38 +02:00
public String getVersion ( ) {
try {
return getPackageManager ( ) . getPackageInfo ( getPackageName ( ) , PackageManager . GET_META_DATA ) . versionName ;
} catch ( PackageManager . NameNotFoundException e ) {
GB . log ( " Unable to determine Gadgetbridge's version " , GB . WARN , e ) ;
return " 0.0.0 " ;
}
}
public String getNameAndVersion ( ) {
try {
ApplicationInfo appInfo = getPackageManager ( ) . getApplicationInfo ( getContext ( ) . getPackageName ( ) , PackageManager . GET_META_DATA ) ;
PackageInfo packageInfo = getPackageManager ( ) . getPackageInfo ( getPackageName ( ) , PackageManager . GET_META_DATA ) ;
return String . format ( " %s %s " , appInfo . name , packageInfo . versionName ) ;
} catch ( PackageManager . NameNotFoundException e ) {
GB . log ( " Unable to determine Gadgetbridge's name/version " , GB . WARN , e ) ;
return " Gadgetbridge " ;
}
}
2015-05-01 09:36:10 +02:00
}