diff --git a/MobileWeather/app/build.gradle b/MobileWeather/app/build.gradle index e24f53f..cc23c37 100644 --- a/MobileWeather/app/build.gradle +++ b/MobileWeather/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 29 + compileSdkVersion 31 defaultConfig { applicationId "com.sdl.mobileweather" minSdkVersion 16 - targetSdkVersion 29 + targetSdkVersion 31 versionCode 27 versionName "1.7.15" testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' @@ -37,8 +37,7 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' - // implementation 'com.smartdevicelink:sdl_android:4.+' - implementation 'com.smartdevicelink:sdl_android:5.0.0' + implementation 'com.smartdevicelink:sdl_android:5.4.0' implementation 'net.hockeyapp.android:HockeySDK:5.1.0' implementation 'com.google.android.gms:play-services-location:16.0.0' } diff --git a/MobileWeather/app/src/main/AndroidManifest.xml b/MobileWeather/app/src/main/AndroidManifest.xml index 70f6b8f..07de1f5 100644 --- a/MobileWeather/app/src/main/AndroidManifest.xml +++ b/MobileWeather/app/src/main/AndroidManifest.xml @@ -6,6 +6,8 @@ + @@ -23,6 +25,8 @@ + + + android:screenOrientation="portrait" + android:exported="true"> @@ -48,9 +53,26 @@ - + + + + + + + + + + - + diff --git a/MobileWeather/app/src/main/java/com/sdl/mobileweather/activity/MainActivity.java b/MobileWeather/app/src/main/java/com/sdl/mobileweather/activity/MainActivity.java index 072d38e..876f7b4 100755 --- a/MobileWeather/app/src/main/java/com/sdl/mobileweather/activity/MainActivity.java +++ b/MobileWeather/app/src/main/java/com/sdl/mobileweather/activity/MainActivity.java @@ -1,5 +1,6 @@ package com.sdl.mobileweather.activity; + import android.Manifest; import android.app.ActionBar; import android.app.ActionBar.Tab; @@ -11,6 +12,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; +import android.os.Build; import android.os.Bundle; import androidx.legacy.app.ActionBarDrawerToggle; import androidx.core.app.ActivityCompat; @@ -27,18 +29,20 @@ import android.widget.ListView; import android.widget.Toast; +import com.sdl.mobileweather.BuildConfig; import com.sdl.mobileweather.R; import com.sdl.mobileweather.fragments.ConditionsFragment; import com.sdl.mobileweather.fragments.ForecastFragment; import com.sdl.mobileweather.smartdevicelink.SdlActivity; import com.sdl.mobileweather.smartdevicelink.SdlApplication; +import com.sdl.mobileweather.smartdevicelink.SdlReceiver; public class MainActivity extends SdlActivity implements ActionBar.TabListener { private static final String SELECTED_NAVIGATION_ITEM = "selected_navigation_item"; private static final String APP_ID = "bf2c3a7bad6b0c79152f50cc42ba1ace"; - private static final int LOCATION_PERMISSION_REQUEST_CODE = 100; + private static final int PERMISSIONS_REQUEST_CODE = 100; private Fragment mCurrentFragment; private DrawerLayout mDrawerLayout; @@ -139,14 +143,41 @@ else if ((getResources().getString(R.string.drawer_item_about)).equals(item)){ private void checkForCrashes() {} private void checkForUpdates() {} - + + private boolean checkPermissions() { + boolean permissionsGranted; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + boolean bluetoothGranted = PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_CONNECT); + boolean locationGranted = PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION); + permissionsGranted = (BuildConfig.TRANSPORT.equals("TCP") || bluetoothGranted) && locationGranted; + } + else { + permissionsGranted = PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION); + } + + return permissionsGranted; + } + + private void requestPermissions() { + String[] permissions; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + permissions = new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION}; + } + else { + permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION}; + } + + ActivityCompat.requestPermissions(this, permissions, PERMISSIONS_REQUEST_CODE); + } + @Override protected void onCreate(Bundle savedInstanceState) { Log.v(SdlApplication.TAG, "onCreate main"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - - + // Create tabs ActionBar bar = getActionBar(); bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); @@ -207,8 +238,8 @@ protected void onStart() { lbManager.registerReceiver(mHourlyForecastReceiver, new IntentFilter("com.sdl.mobileweather.HourlyForecast")); // Ask for permissions - if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); + if (!checkPermissions()) { + requestPermissions(); } else { startServices(); } @@ -367,10 +398,10 @@ public void onSaveInstanceState(Bundle outState) { } @Override - public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { - if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED){ - Toast.makeText(this, "The app cannot run without this permission!", Toast.LENGTH_SHORT).show(); + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_CODE) { + if (!checkPermissions()) { + Toast.makeText(this, "The app cannot run without these permissions!", Toast.LENGTH_SHORT).show(); finish(); } else { startServices(); diff --git a/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlReceiver.java b/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlReceiver.java index 594b0b1..1c94004 100644 --- a/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlReceiver.java +++ b/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlReceiver.java @@ -1,5 +1,6 @@ package com.sdl.mobileweather.smartdevicelink; +import android.app.PendingIntent; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; @@ -8,6 +9,7 @@ import com.smartdevicelink.transport.SdlBroadcastReceiver; import com.smartdevicelink.transport.SdlRouterService; +import com.smartdevicelink.transport.TransportConstants; public class SdlReceiver extends SdlBroadcastReceiver { @@ -44,14 +46,25 @@ public void onSdlEnabled(Context context, Intent intent) { //Use the provided intent but set the class to the SdlService intent.setClass(context, SdlService.class); - -// SdlService needs to be foregrounded in Android O and above -// This will prevent apps in the background from crashing when they try to start SdlService -// Because Android O doesn't allow background apps to start background services - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(intent); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (intent.getParcelableExtra(TransportConstants.PENDING_INTENT_EXTRA) != null) { + PendingIntent pendingIntent = (PendingIntent) intent.getParcelableExtra(TransportConstants.PENDING_INTENT_EXTRA); + try { + //Here we are allowing the RouterService that is in the Foreground to start the SdlService on our behalf + pendingIntent.send(context, 0, intent); + } catch (PendingIntent.CanceledException e) { + e.printStackTrace(); + } + } } else { - context.startService(intent); + // SdlService needs to be foregrounded in Android O and above + // This will prevent apps in the background from crashing when they try to start SdlService + // Because Android O doesn't allow background apps to start background services + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent); + } else { + context.startService(intent); + } } } diff --git a/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlService.java b/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlService.java index ab95715..9fc7d64 100644 --- a/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlService.java +++ b/MobileWeather/app/src/main/java/com/sdl/mobileweather/smartdevicelink/SdlService.java @@ -75,6 +75,7 @@ import com.smartdevicelink.transport.TCPTransportConfig; import com.smartdevicelink.util.DebugTool; +import com.smartdevicelink.util.SystemInfo; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -737,6 +738,11 @@ public LifecycleConfigurationUpdate managerShouldUpdateLifecycle(Language langua return null; } } + + @Override + public boolean onSystemInfoReceived(SystemInfo systemInfo) { + return true; + } }; // Create App Icon, this is set in the SdlManager builder diff --git a/MobileWeather/app/src/main/java/com/sdl/mobileweather/weather/WeatherAlarmManager.java b/MobileWeather/app/src/main/java/com/sdl/mobileweather/weather/WeatherAlarmManager.java index 65baa72..5391ff3 100644 --- a/MobileWeather/app/src/main/java/com/sdl/mobileweather/weather/WeatherAlarmManager.java +++ b/MobileWeather/app/src/main/java/com/sdl/mobileweather/weather/WeatherAlarmManager.java @@ -1,5 +1,6 @@ package com.sdl.mobileweather.weather; +import android.os.Build; import java.util.Calendar; import android.app.AlarmManager; @@ -148,10 +149,15 @@ private void restartAlarm(Context context) { if (mAlarmManager != null && mAlarmIntent != null) { mAlarmManager.cancel(mAlarmIntent); } - - mAlarmIntent = PendingIntent.getBroadcast(context, PENDING_INTENT_ID, mUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - Calendar cal = Calendar.getInstance(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + mAlarmIntent = PendingIntent.getBroadcast(context, PENDING_INTENT_ID, mUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + } + else { + mAlarmIntent = PendingIntent.getBroadcast(context, PENDING_INTENT_ID, mUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT); + } + + Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(System.currentTimeMillis()); cal.add(Calendar.MINUTE, mUpdateInterval); Log.d(SdlApplication.TAG, "restartAlarm mUpdateInterval = " + mUpdateInterval);