2017-01-05 3 views
0

Я использую hotchemi PermissionsDispatcher для проверки разрешений. Он отлично работает для API> = 23. Но я получаю FATAL EXCEPTION java.lang.StackOverflowError, когда пытаюсь использовать тот же код на устройстве с API 16. Ошибка возникает при вызове showCameraWithCheck() в сгенерированном классе MainActivityPermissionsDispatcherAndroid PermissionsDispatcher с API <23

Я глубоко погрузился в класс MainActivityPermissionsDispatcher, сгенерированный библиотекой PermissionsDispatcher, и нашел, почему происходит переполнение стека. Когда я звоню MainActivityPermissionsDispatcher.showCameraWithCheck(this); он идет к этому методу в сформированном 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); 
    } 
} 

}

Дело в том, PermissionUtils.hasSelfPermissions(target, PERMISSION_SHOWCAMERA) всегда верно, так это называется target.showCamera() это мой метод, который называется MainActivityPermissionsDispatcher.showCameraWithCheck(this); так войти в не end loop .... Я предполагаю, что метод hasSelfPermissions() проверяет, являются ли его разрешениями времени выполнения (API> = 23) или разрешениями старого стиля (< API 23).

Е/AndroidRuntime: неустранимое: Главный java.lang.StackOverflowError на android.os.Parcel.readException (Parcel.java:1376) на android.app.ActivityManagerProxy.checkPermission (ActivityManagerNative.java : 2874) на android.app.ContextImpl.checkPermission (ContextImpl.java:1285) на android.content.ContextWrapper.checkPermission (ContextWrapper.java:421) на android.support.v4.content.PermissionCh ecker.checkPermission (PermissionChecker.java:89) на android.support.v4.content.PermissionChecker.checkSelfPermission (PermissionChecker.java:125) на permissions.dispatcher.PermissionUtils.hasSelfPermissions (PermissionUtils.java:73) на com.example.android.permissionsdispatcherapp.MainActivityPermissionsDispatcher.showCameraWithCheck (MainActivityPermissionsDispatcher.java:20) на com.example.android.permissionsdispatcherapp.MainActivity.showCamera (MainActivity.java:52) ......... .........

@RuntimePermissions 
public class MainActivity extends AppCompatActivity { 
private static String LOG_TAG = MainActivity.class.getSimpleName(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    try { 

     Button btnShowCamera = (Button) findViewById(R.id.btn_show_camera); 
     btnShowCamera.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Log.i(LOG_TAG, "Show camera button pressed."); 
       showCamera(); 
      } 

     }); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

@NeedsPermission(Manifest.permission.CAMERA) 
void showCamera() { 
    // NOTE: delegate the permission handling to generated method 
    // ERROR 
    MainActivityPermissionsDispatcher.showCameraWithCheck(this); 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
    // NOTE: delegate the permission handling to generated method 
    MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults); 
} 

@OnPermissionDenied(Manifest.permission.CAMERA) 
void onCameraDenied() { 
    // NOTE: Deal with a denied permission, e.g. by showing specific UI 
    // or disabling certain functionality 
    Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_LONG).show(); 
} 

@OnNeverAskAgain(Manifest.permission.CAMERA) 
void onCameraNeverAskAgain() { 
    Toast.makeText(this, R.string.permission_camera_never_askagain, Toast.LENGTH_LONG).show(); 
} 

@OnShowRationale(Manifest.permission.CAMERA) 
void showRationaleForCamera(PermissionRequest request) { 
    // NOTE: Show a rationale to explain why the permission is needed, e.g. with a dialog. 
    // Call proceed() or cancel() on the provided PermissionRequest to continue or abort 
    showRationaleDialog(R.string.permission_camera_rationale, request); 
} 

private void showRationaleDialog(@StringRes int messageResId, 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(); 
       } 
      }) 
      .setCancelable(false) 
      .setMessage(messageResId) 
      .show(); 
} 
} 

enter code here 

ответ

1

Обнаружили путь. Мой код был неправильным. Не нужно вызывать метод showCamera(), потому что сгенерированный класс MainActivityPermissionsDispatcher уже делает это. Поскольку API 16 не имеет разрешений времени выполнения, он заканчивается этим концом конца.

Это исправление:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    try { 
      Button btnShowCamera = (Button) findViewById(R.id.btn_show_camera); 
      btnShowCamera.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
      Log.i(LOG_TAG, "Show camera button pressed."); 
      askForPermission(); 
      } 

     }); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

void askForPermission() { 
    MainActivityPermissionsDispatcher.showCameraWithCheck(this); 
} 

@NeedsPermission(Manifest.permission.CAMERA) 
void showCamera() { 
    Toast.makeText(this, "Showing camera", Toast.LENGTH_LONG).show(); 
} 
Смежные вопросы