Skip to content
This repository has been archived by the owner on Apr 9, 2021. It is now read-only.

[MRG] Add the location permission for android 9. #286

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions skunkworks_crow/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ dependencies {

//MPAndroidChart
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'

// Permissions Dispatcher
implementation "org.permissionsdispatcher:permissionsdispatcher:4.5.0"
lakshyagupta21 marked this conversation as resolved.
Show resolved Hide resolved
annotationProcessor "org.permissionsdispatcher:permissionsdispatcher-processor:4.5.0"
}
22 changes: 22 additions & 0 deletions skunkworks_crow/src/main/assets/open_source_licenses.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ <h3>
Apache License Version 2.0, January 2004
</h3>
<ul>
<li>
<b>PermissionsDispatcher</b>
</li>
<li>
<b>Dagger 2</b>
</li>
Expand Down Expand Up @@ -85,5 +88,24 @@ <h3>
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
</pre>

<h3>
The MIT License (MIT)
</h3>
<ul>
<li>
<b>Mockito</b>
</li>
<li>
<b>Robolectric</b>
</li>
</ul>
<pre>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</pre>

</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.location.LocationManager;
import android.net.Uri;
import android.provider.Settings;

import androidx.appcompat.app.AlertDialog;
Expand All @@ -20,6 +21,8 @@
*/
public class PermissionUtils {

private static final String SCHEME = "package";

private PermissionUtils() {
}

Expand Down Expand Up @@ -56,6 +59,30 @@ public static void showLocationAlertDialog(Activity targetActivity) {
builder.setCancelable(false);
builder.show();
}

/**
* Showing an alert dialog and send users to app info page.
*/
public static void showAppInfo(Activity targetActivity, String packageName) {
AlertDialog.Builder builder = new AlertDialog.Builder(targetActivity);
builder.setMessage(R.string.permission_open_info);

builder.setPositiveButton(targetActivity.getString(R.string.permission_open_info_button), (DialogInterface dialog, int which) -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts(SCHEME, packageName, null);
intent.setData(uri);
targetActivity.startActivity(intent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue over here when the user moves to app settings, and no matter what he does there and after doing all the activity on app settings when he presses back he goes back to the Send data screen with empty view.
You should check whenever an activity is resumed, whether user actually left application to actually play with the app settings, if the answer is yes then check if we've enough permission to do the transmission, if not then again display the same dialog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I tested in android 9 and non-android 9 devices, no issues, but I think it still needs more tests.

});

builder.setNegativeButton(targetActivity.getString(R.string.cancel), (DialogInterface dialog, int which) -> {
dialog.dismiss();
targetActivity.finish();
});

builder.setCancelable(false);
builder.show();
}
}


Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package org.odk.share.views.ui.bluetooth;

import android.Manifest;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
Expand All @@ -22,21 +25,28 @@
import org.odk.share.rx.RxEventBus;
import org.odk.share.rx.schedulers.BaseSchedulerProvider;
import org.odk.share.services.ReceiverService;
import org.odk.share.utilities.PermissionUtils;
import org.odk.share.views.ui.common.injectable.InjectableActivity;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.RuntimePermissions;
import timber.log.Timber;

/**
* Receive activity, for testing, needs refactor.
*
* @author huangyz0918 (huangyz0918@gmail.com)
*/
@RuntimePermissions
public class BtReceiverActivity extends InjectableActivity implements
BluetoothReceiver.BluetoothReceiverListener, BluetoothListAdapter.OnDeviceClickListener {

Expand Down Expand Up @@ -83,12 +93,29 @@ protected void onCreate(Bundle savedInstanceState) {
// checking for if bluetooth enabled
if (!BluetoothUtils.isBluetoothEnabled()) {
BluetoothUtils.enableBluetooth();
updateDeviceList();
updateDeviceListWithPermissionCheck();
}

setupScanningDialog();
}

/**
* Init the basic events for our views.
*/
private void initEvents() {
progressDialog = new ProgressDialog(this);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(bluetoothListAdapter);
bluetoothReceiver = new BluetoothReceiver(this, this);

updateDeviceListWithPermissionCheck();
}

/**
* build a new progress dialog waiting for the scanning progress.
*/
Expand All @@ -106,33 +133,60 @@ private void setupScanningDialog() {
/**
* Rescan the bluetooth devices and update the list.
*/
public void updateDeviceList() {
@NeedsPermission({Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION})
void updateDeviceList() {
if (!bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.startDiscovery();
}
bluetoothListAdapter.notifyDataSetChanged();
}

private void initEvents() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(bluetoothListAdapter);
bluetoothReceiver = new BluetoothReceiver(this, this);
bluetoothAdapter.startDiscovery();

// click to refresh the devices list.
btnRefresh.setOnClickListener((View v) -> {
if (BluetoothUtils.isBluetoothEnabled()) {
updateDeviceList();
} else {
BluetoothUtils.enableBluetooth();
Toast.makeText(this, "bluetooth has been disabled, turning on...", Toast.LENGTH_SHORT).show();
}
});
@SuppressWarnings("CallNeedsPermission")
private void updateDeviceListWithPermissionCheck() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
BtReceiverActivityPermissionsDispatcher.updateDeviceListWithPermissionCheck(this);
} else {
updateDeviceList();
}
}

/**
* If the permission was denied, finishing this activity.
*/
@OnPermissionDenied({Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION})
void showDeniedForLocation() {
Toast.makeText(this, R.string.permission_location_denied, Toast.LENGTH_SHORT).show();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the toast length to LONG, everywhere

finish();
}

/**
* If clicked the "never ask", we should show a toast to guide user.
*/
@OnNeverAskAgain({Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION})
void showNeverAskForLocation() {
PermissionUtils.showAppInfo(this, getPackageName());
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
BtReceiverActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}

/**
* Clicking to refresh the devices list.
*/
@OnClick(R.id.btn_refresh)
public void refresh() {
if (BluetoothUtils.isBluetoothEnabled()) {
updateDeviceListWithPermissionCheck();
} else {
BluetoothUtils.enableBluetooth();
Toast.makeText(this, "bluetooth has been disabled, turning on...", Toast.LENGTH_SHORT).show();
}
}

/**
Expand Down Expand Up @@ -217,6 +271,9 @@ public void onDiscoveryFinished() {
checkEmptyList();
}

/**
* Clicking the item to connect.
*/
@Override
public void onItemClick(BluetoothDevice device) {
if (BluetoothUtils.isBluetoothEnabled()) {
Expand All @@ -225,7 +282,6 @@ public void onItemClick(BluetoothDevice device) {
}

receiverService.startBtDownloading(device.getAddress());
progressDialog = new ProgressDialog(this);
progressDialog.setTitle(getString(R.string.connecting_title));
progressDialog.setMessage(getString(R.string.connecting_message));
progressDialog.setIndeterminate(true);
Expand Down
Loading