Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducing PermissionsDispatcher

Introducing PermissionsDispatcher

@hotchemi

June 10, 2016
Tweet

More Decks by @hotchemi

Other Decks in Programming

Transcript

  1. • From Marshmallow • Grant permissions at runtime • User

    can revoke permissions
 from settings screen
  2. • Never ask again • Once user check and denied,


    checkSelfPermission always 
 return PERMISSION_DENIED • targetSdkVersion >= 23 • Lead user to settings screen
  3. public class MainActivity extends AppCompatActivity { 
 @Override protected void

    onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); 
 showCamera(); 
 
 } }
  4. public class MainActivity extends AppCompatActivity { 
 @Override protected void

    onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); showCamera(); 
 
 
 } } private static final int REQUEST_SHOWCAMERA = 0;
  5. public class MainActivity extends AppCompatActivity { private static final int

    REQUEST_SHOWCAMERA = 0; 
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); showCamera(); 
 
 
 } } private static final String[] PERMISSION_SHOWCAMERA = new String[]{"android.permission.CAMERA"};
  6. public class MainActivity extends AppCompatActivity { private static final int

    REQUEST_SHOWCAMERA = 0; private static final String[] PERMISSION_SHOWCAMERA = new String[]{"android.permission.CAMERA"}; 
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); 
 
 
 } } if (PermissionChecker.checkSelfPermissions(this, PERMISSION_SHOWCAMERA) == PERMISSION_GRANTED) {
 showCamera(); } else {
 if (ActivityCompat.shouldShowRequestPermissionRationale(this, PERMISSION_SHOWCAMERA)) {
 // show rationale
 }
 ActivityCompat.requestPermissions(this, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA); }
  7. public class MainActivity extends AppCompatActivity { private static final int

    REQUEST_SHOWCAMERA = 0; private static final String[] PERMISSION_SHOWCAMERA = new String[]{"android.permission.CAMERA"}; 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main); if (PermissionChecker.checkSelfPermissions(this, PERMISSION_SHOWCAMERA) == PERMISSION_GRANTED) {
 showCamera(); } else {
 if (ActivityCompat.shouldShowRequestPermissionRationale(this, PERMISSION_SHOWCAMERA)) {
 // show rationale
 }
 ActivityCompat.requestPermissions(this, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
 switch (requestCode) {
 case REQUEST_SHOWCAMERA:
 if (PermissionUtils.verifyPermissions(grantResults)) { // check all permissions are granted
 showCamera();
 } else { if (ActivityCompat.shouldShowRequestPermissionRationale(this, PERMISSION_SHOWCAMERA)) { // show denied action } else { // never ask again } }
 break;
 }
  8. • PermissionsDispatcher • Generate codes with annotation processing • supported

    on API levels 4 and up • Processor module is written with Kotlin • https://github.com/hotchemi/PermissionsDispatcher
  9. • Simple annotation based API • @RuntimePermissions ✔ • @NeedsPermission

    ✔ • @OnDeniedPermission • @OnShowRationale • @NeverAskAgain
  10. • @RuntimePermissions • Activity • Fragment • Fragment(support v4) public

    class MainActivity extends AppCompatActivity{ } @RuntimePermissions
  11. • @NeedsPermission • Single permission • Multiple permissions void showCamera()

    {
 getSupportFragmentManager().beginTransaction()
 .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
 .addToBackStack("camera")
 .commitAllowingStateLoss();
 }
  12. • @NeedsPermission • Single permission • Multiple permissions void showCamera()

    {
 getSupportFragmentManager().beginTransaction()
 .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
 .addToBackStack("camera")
 .commitAllowingStateLoss();
 } @NeedsPermission(Manifest.permission.CAMERA)
  13. • @OnPermissionDenied • Single permission • Multiple permissions 
 void

    onCameraDenied() {
 Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_LONG).show();
 }
  14. • @OnPermissionDenied • Single permission • Multiple permissions 
 void

    onCameraDenied() {
 Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_LONG).show();
 } @OnPermissionDenied(Manifest.permission.CAMERA)
  15. • @OnShowRationale • Asynchronous support 
 
 void showRationaleForCamera(final PermissionRequest

    request) {
 new AlertDialog.Builder(this)
 .setPositiveButton(R.string.button_allow, new DialogInterface.OnClickListener() {
 @Override public void onClick(@NonNull DialogInterface dialog, int which) {
 request.proceed();
 } })
 .setNegativeButton(R.string.button_deny, new DialogInterface.OnClickListener() {
 @Override public void onClick(@NonNull DialogInterface dialog, int which) {
 request.cancel();
 } })
 .setMessage(R.string.permission_camera_rationale)
 .show();
 }
  16. • @OnShowRationale • Asynchronous support 
 @OnShowRationale(Manifest.permission.CAMERA) 
 
 void

    showRationaleForCamera(final PermissionRequest request) {
 new AlertDialog.Builder(this)
 .setPositiveButton(R.string.button_allow, new DialogInterface.OnClickListener() {
 @Override public void onClick(@NonNull DialogInterface dialog, int which) {
 request.proceed();
 } })
 .setNegativeButton(R.string.button_deny, new DialogInterface.OnClickListener() {
 @Override public void onClick(@NonNull DialogInterface dialog, int which) {
 request.cancel();
 } })
 .setMessage(R.string.permission_camera_rationale)
 .show();
 }
  17. • @NeverAskAgain • Single permission • Multiple permissions 
 void

    onNeverAskAgain() {
 Toast.makeText(this, R.string.permission_camera_neveraskagain, Toast.LENGTH_LONG).show();
 }
  18. • @NeverAskAgain • Single permission • Multiple permissions 
 void

    onNeverAskAgain() {
 Toast.makeText(this, R.string.permission_camera_neveraskagain, Toast.LENGTH_LONG).show();
 } @NeverAskAgain(Manifest.permission.CAMERA)
  19. package permissions.dispatcher.sample;
 
 @RuntimePermissions
 public class MainActivity extends AppCompatActivity implements

    View.OnClickListener {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 findViewById(R.id.button_camera).setOnClickListener(this);
 }
 
 @Override
 public void onClick(@NonNull View v) {
 switch (v.getId()) {
 case R.id.button_camera:
 MainActivityPermissionsDispatcher.showCameraWithCheck(this);
 break;
 }
 }
 
 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
 } 
 } 
 
 
 
 MainActivityPermissionsDispatcher.showCameraWithCheck(this); 
 
 
 MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
  20. package permissions.dispatcher.sample;
 
 final class MainActivityPermissionsDispatcher {
 private static final

    int REQUEST_SHOWCAMERA = 0;
 
 private static final String[] PERMISSION_SHOWCAMERA = new String[] {"android.permission.CAMERA"};
 
 private MainActivityPermissionsDispatcher() {
 }
 
 static void showCameraWithCheck(MainActivity target) {
 if (PermissionUtils.hasSelfPermissions(target, PERMISSION_SHOWCAMERA)) {
 target.showCamera();
 } else {
 if (PermissionUtils.shouldShowRequestPermissionRationale(target, PERMISSION_SHOWCAMERA)) {
 target.showRationaleForCamera(new ShowCameraPermissionRequest(target));
 } else {
 ActivityCompat.requestPermissions(target, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA);
 }
 }
 }
 
 static void onRequestPermissionsResult(MainActivity target, int requestCode, int[] grantResults) {
 switch (requestCode) {
 case REQUEST_SHOWCAMERA:
 if (PermissionUtils.verifyPermissions(grantResults)) {
 target.showCamera();
 } else {
 target.onCameraDenied();
 }
 break;
 default:
 break;
 }
 }
 
 private static final class ShowCameraPermissionRequest implements PermissionRequest {
 private final WeakReference<MainActivity> weakTarget;
 
 private ShowCameraPermissionRequest(MainActivity target) {
 this.weakTarget = new WeakReference<>(target);
 }
 
 @Override
 public void proceed() {
 MainActivity target = weakTarget.get();
 if (target == null) return;
 ActivityCompat.requestPermissions(target, PERMISSION_SHOWCAMERA, REQUEST_SHOWCAMERA);
 }
 
 @Override
 public void cancel() {
 MainActivity target = weakTarget.get();
 if (target == null) return;
 target.onCameraDenied();
 }
 }
 } Generated code