diff --git a/drip-android-observer-master/Android/app/src/main/AndroidManifest.xml b/drip-android-observer-master/Android/app/src/main/AndroidManifest.xml index 729e8bcd701e0b3b080544fdea17309e369a881a..6dbd13ddc2c8f5cc81867e54eb714e35d6c62052 100644 --- a/drip-android-observer-master/Android/app/src/main/AndroidManifest.xml +++ b/drip-android-observer-master/Android/app/src/main/AndroidManifest.xml @@ -7,9 +7,9 @@ android:maxSdkVersion="30"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/> + <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> diff --git a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/Constants.java b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/Constants.java index 6ee51171515484f305d7cf21718586e95df7f222..6e55a292170887b26eabbd0d4da32779bfb9a7ae 100644 --- a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/Constants.java +++ b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/Constants.java @@ -7,11 +7,6 @@ package org.dripdronescanner.android; public class Constants { - public static final int REQUEST_BT_CONNECT = 1; - public static final int FINE_LOCATION_PERMISSION_REQUEST_CODE = 2; - public static final int REQUEST_ENABLE_WIFI = 3; - public static final int REQUEST_BT_SCAN = 4; - public static final String DELIM = ","; public static final int MAX_ID_BYTE_SIZE = 20; diff --git a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/AircraftMapView.java b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/AircraftMapView.java index 72f5f06c19668266f0f8ae000c29d618bcaf3c6d..27725e634323568caaee25cba7f7702c7ca621d6 100644 --- a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/AircraftMapView.java +++ b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/AircraftMapView.java @@ -11,8 +11,6 @@ import android.view.ViewGroup; import android.util.Log; import android.widget.ImageButton; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; import androidx.core.app.ActivityCompat; import androidx.core.content.res.ResourcesCompat; import androidx.fragment.app.Fragment; @@ -20,8 +18,6 @@ import androidx.annotation.Nullable; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; -import org.dripdronescanner.android.Constants; -import org.dripdronescanner.android.PermissionUtils; import org.dripdronescanner.android.R; import org.dripdronescanner.android.data.AircraftObject; import org.dripdronescanner.android.data.LocationData; @@ -96,14 +92,10 @@ public class AircraftMapView extends Fragment { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION); return; } - overlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map); - overlay.enableMyLocation(); - overlay.enableFollowLocation(); - map.getOverlays().add(overlay); + enableMyLocation(); }); ImageButton centerMapButton = v.findViewById(R.id.ic_center_map); @@ -115,6 +107,13 @@ public class AircraftMapView extends Fragment { return v; } + public void enableMyLocation() { + overlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map); + overlay.enableMyLocation(); + overlay.enableFollowLocation(); + map.getOverlays().add(overlay); + } + @Override public void onResume() { super.onResume(); @@ -298,21 +297,4 @@ public class AircraftMapView extends Fragment { } } } - - private final ActivityResultLauncher<String> requestPermissionLauncher = - registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { - if (isGranted) { - overlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map); - overlay.enableMyLocation(); - overlay.enableFollowLocation(); - map.getOverlays().add(overlay); - } else { - //showErrorText(R.string.permission_required_toast); - // Explain to the user that the feature is unavailable because the - // feature requires a permission that the user has denied. At the - // same time, respect the user's decision. Don't link to system - // settings in an effort to convince the user to change their - // decision. - } - }); } \ No newline at end of file diff --git a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/DebugActivity.java b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/DebugActivity.java index 04fbd610e8f2090cc9c0ab0c74d02d80d679e7be..4442b198515907acfd5a908dd30aa29f4928857c 100644 --- a/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/DebugActivity.java +++ b/drip-android-observer-master/Android/app/src/main/java/org/dripdronescanner/android/app/DebugActivity.java @@ -14,6 +14,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Location; +import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; @@ -26,11 +27,14 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; -import androidx.annotation.NonNull; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; @@ -40,8 +44,6 @@ import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; -import org.dripdronescanner.android.Constants; -import org.dripdronescanner.android.PermissionUtils; import org.dripdronescanner.android.R; import org.dripdronescanner.android.data.AircraftObject; import org.dripdronescanner.android.log.LogWriter; @@ -53,8 +55,11 @@ import org.dripdronescanner.android.network.WiFiNaNScanner; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.Locale; +import java.util.Map; import java.util.Set; public class DebugActivity extends AppCompatActivity { @@ -79,6 +84,13 @@ public class DebugActivity extends AppCompatActivity { private Handler handler; private Runnable runnableCode; + private AlertDialog alertDialog; + private ArrayList<String> permissionsList; + private final String[] permissionsStr = { + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.BLUETOOTH_CONNECT, + Manifest.permission.BLUETOOTH_SCAN}; + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); @@ -105,7 +117,6 @@ public class DebugActivity extends AppCompatActivity { }); } - @TargetApi(Build.VERSION_CODES.O) private void checkBluetoothSupport(Menu menu) { Object object = getSystemService(BLUETOOTH_SERVICE); if (object == null) @@ -113,27 +124,23 @@ public class DebugActivity extends AppCompatActivity { BluetoothAdapter bluetoothAdapter = ((android.bluetooth.BluetoothManager) object).getAdapter(); if (bluetoothAdapter != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && bluetoothAdapter.isLeCodedPhySupported()) { + if (bluetoothAdapter.isLeCodedPhySupported()) { menu.findItem(R.id.coded_phy).setTitle(R.string.coded_phy_supported); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && bluetoothAdapter.isLeExtendedAdvertisingSupported()) { + if (bluetoothAdapter.isLeExtendedAdvertisingSupported()) { menu.findItem(R.id.extended_advertising).setTitle(R.string.ea_supported); } } } - @TargetApi(Build.VERSION_CODES.O) private void checkNaNSupport(Menu menu) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) { + if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) { menu.findItem(R.id.wifi_nan).setTitle(R.string.nan_supported); } } - @TargetApi(Build.VERSION_CODES.M) private void checkWiFiSupport(Menu menu) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - menu.findItem(R.id.wifi_beacon_scan).setTitle(R.string.wifi_beacon_scan_supported); - } + menu.findItem(R.id.wifi_beacon_scan).setTitle(R.string.wifi_beacon_scan_supported); } @Override @@ -191,9 +198,6 @@ public class DebugActivity extends AppCompatActivity { private void createNewLogfile() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - requestBluetoothConnectPermission(Constants.REQUEST_BT_CONNECT); - } return; } loggerFile = getLoggerFileDir(btScanner.getBluetoothAdapter().getName()); @@ -213,6 +217,18 @@ public class DebugActivity extends AppCompatActivity { setContentView(R.layout.activity_debug); mModel = ViewModelProviders.of(this).get(AircraftViewModel.class); + // Ask for permissions for SDK >= 31 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + permissionsList = new ArrayList<>(); + permissionsList.addAll(Arrays.asList(permissionsStr)); + askForPermissions(permissionsList); + // Ask for permissions for 29 <= SDK <= 31 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + permissionsList = new ArrayList<>(); + permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION); + askForPermissions(permissionsList); + } + dataManager = new OpenDroneIdDataManager(new OpenDroneIdDataManager.Callback() { @Override public void onNewAircraft(AircraftObject object) { @@ -222,40 +238,17 @@ public class DebugActivity extends AppCompatActivity { btScanner = new BluetoothScanner(this, dataManager); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && - getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) { + if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) { WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); if (!wifiManager.isWifiEnabled()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - Intent panelIntent = new Intent(Settings.Panel.ACTION_WIFI); - startActivityForResult(panelIntent, Constants.REQUEST_ENABLE_WIFI); - } else { - wifiManager.setWifiEnabled(true); - wifiOn = true; - } + wifiManager.setWifiEnabled(true); + wifiOn = true; } } BluetoothAdapter bluetoothAdapter = btScanner.getBluetoothAdapter(); if (bluetoothAdapter != null) { createNewLogfile(); - // Is Bluetooth turned on? - if (!bluetoothAdapter.isEnabled()) { - // Prompt user to turn on Bluetooth (logic continues in onActivityResult()). - Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, Constants.REQUEST_BT_CONNECT); - } else { - bluetoothOn = true; - // Check permission - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED - && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - Log.d(TAG, "onMapReady: call request permission"); - requestLocationPermission(Constants.FINE_LOCATION_PERMISSION_REQUEST_CODE); - } else { - - initialize(); - } - } } else { // Bluetooth is not supported. showErrorText(R.string.bt_not_supported); @@ -296,58 +289,16 @@ public class DebugActivity extends AppCompatActivity { mModel.getAllAircraft().observe(this, listObserver); - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - requestBluetoothScanPermission(Constants.REQUEST_BT_SCAN); - } - return; - } btScanner.startScan(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - wiFiNaNScanner = new WiFiNaNScanner(this, dataManager, logger); - wiFiNaNScanner.startScan(); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - wiFiBeaconScanner = new WiFiBeaconScanner(this, dataManager, logger); - if (wiFiBeaconScanner != null) { - wiFiBeaconScanner.startScan(); - } - } + wiFiNaNScanner = new WiFiNaNScanner(this, dataManager, logger); + wiFiNaNScanner.startScan(); + wiFiBeaconScanner = new WiFiBeaconScanner(this, dataManager, logger); + wiFiBeaconScanner.startScan(); addDeviceList(); } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == Constants.REQUEST_BT_CONNECT) { - if (resultCode == RESULT_OK) { - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED - && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - Log.d(TAG, "onMapReady: call request permission"); - requestLocationPermission(Constants.FINE_LOCATION_PERMISSION_REQUEST_CODE); - } else { - initialize(); - } - } else { - if(!wifiOn) { - // User declined to enable Bluetooth, exit the app. - Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_LONG).show(); - finish(); - } - } - } else if (requestCode == Constants.REQUEST_ENABLE_WIFI) { - WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); - if (!wifiManager.isWifiEnabled() && !bluetoothOn) { - Toast.makeText(this, R.string.wifi_not_enabled_leaving, Toast.LENGTH_LONG).show(); - finish(); - } - } else { - super.onActivityResult(requestCode, resultCode, data); - } - } - public void addDeviceList() { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.holder, new DeviceList()).commitAllowingStateLoss(); @@ -381,60 +332,70 @@ public class DebugActivity extends AppCompatActivity { Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show(); } - public void requestLocationPermission(int requestCode) { - Log.d(TAG, "requestLocationPermission: request permission"); - - // Location permission has not been granted yet, request it. - PermissionUtils.requestPermission(this, requestCode, - Manifest.permission.ACCESS_FINE_LOCATION, false); - } - - @RequiresApi(api = Build.VERSION_CODES.S) - public void requestBluetoothConnectPermission(int requestCode) { - Log.d(TAG, "requestBluetoothConnectPermission: request permission"); - - // Bluetooth permission has not been granted yet, request it. - PermissionUtils.requestPermission(this, requestCode, - Manifest.permission.BLUETOOTH_CONNECT, false); + private final ActivityResultLauncher<String[]> permissionsLauncher = + registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), + new ActivityResultCallback<Map<String, Boolean>>() { + @Override + public void onActivityResult(Map<String,Boolean> result) { + ArrayList<Boolean> list = new ArrayList<>(result.values()); + permissionsList = new ArrayList<>(); + int permissionsCount = 0; + for (int i = 0; i < list.size(); i++) { + if (shouldShowRequestPermissionRationale(permissionsStr[i])) { + permissionsList.add(permissionsStr[i]); + }else if (!hasPermission(DebugActivity.this, permissionsStr[i])){ + permissionsCount++; + } + } + if (permissionsList.size() > 0) { + // Some permissions are denied and can be asked again. + askForPermissions(permissionsList); + } else if (permissionsCount > 0) { + showPermissionDialog(); + } else { + // All permissions granted. + initialize(); + AircraftMapView aircraftMapViewFragment = (AircraftMapView) getSupportFragmentManager().findFragmentById(R.id.mapView); + if (aircraftMapViewFragment != null) { + aircraftMapViewFragment.enableMyLocation(); + } + } + } + }); + + private void askForPermissions(ArrayList<String> permissionsList) { + String[] newPermissionStr = new String[permissionsList.size()]; + for (int i = 0; i < newPermissionStr.length; i++) { + newPermissionStr[i] = permissionsList.get(i); + } + if (newPermissionStr.length > 0) { + permissionsLauncher.launch(newPermissionStr); + } else { + /* User has pressed 'Deny & Don't ask again' so we have to show the enable permissions dialog + which will lead them to app details page to enable permissions from there. */ + showPermissionDialog(); + } } - @RequiresApi(api = Build.VERSION_CODES.S) - public void requestBluetoothScanPermission(int requestCode) { - Log.d(TAG, "requestBluetoothConnectPermission: request permission"); - - // Bluetooth permission has not been granted yet, request it. - PermissionUtils.requestPermission(this, requestCode, - Manifest.permission.BLUETOOTH_SCAN, false); + private boolean hasPermission(Context context, String permissionStr) { + return ContextCompat.checkSelfPermission(context, permissionStr) == PackageManager.PERMISSION_GRANTED; } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == Constants.FINE_LOCATION_PERMISSION_REQUEST_CODE) { - Log.d(TAG, "onRequestPermissionsResult: back from request FINE_LOCATION"); - if (PermissionUtils.isPermissionGranted(permissions, grantResults, - Manifest.permission.ACCESS_FINE_LOCATION)) { - initialize(); - } else { - showErrorText(R.string.permission_required_toast); - } - - } else if (requestCode == Constants.REQUEST_BT_CONNECT) { - Log.d(TAG, "onRequestPermissionsResult: back from request BLUETOOTH_CONNECT"); - if (PermissionUtils.isPermissionGranted(permissions, grantResults, - Manifest.permission.BLUETOOTH_CONNECT)) { - initialize(); - } else { - showErrorText(R.string.bluetooth_connect_permission_required_toast); - } - } else if (requestCode == Constants.REQUEST_BT_SCAN) { - Log.d(TAG, "onRequestPermissionsResult: back from request BLUETOOTH_SCAN"); - if (PermissionUtils.isPermissionGranted(permissions, grantResults, - Manifest.permission.BLUETOOTH_SCAN)) { - initialize(); - } else { - showErrorText(R.string.bluetooth_scan_permission_required_toast); + private void showPermissionDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Permission required") + .setMessage("Some permissions are need to be allowed to use this app without any problems.") + .setPositiveButton("Settings", (dialog, which) -> { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getPackageName(), null); + intent.setData(uri); + startActivity(intent); + dialog.dismiss(); + }); + if (alertDialog == null) { + alertDialog = builder.create(); + if (!alertDialog.isShowing()) { + alertDialog.show(); } } }