如何从服务中检查新的 android 6.0 权限

How to check new android 6.0 Permissions from service

我有一个 Android 6.0 应用程序,其未绑定 android 服务连接到 Google API 以接收 Fused API 位置提供商更新。为此,我需要 ACCESS_FINE_LOCATION 权限。 在 Marshmallow 更新之前,一切都运行良好。现在我需要为我的应用实施新的权限模型。

我了解到无法直接从服务中检查 android 6.0 权限。

我所有的位置更新接收器和 Google APi 客户端连接部分都由服务处理并在服务中处理,我会链接到那里!

是否可以在活动中检查一次权限,然后在服务启动时将其处理给服务,并且权限在服务的生命周期内保留在服务中?还是我必须检查每个 LocationUpdate 的权限?

我如何才能为我的服务实施权限检查?有人做过吗?你能给我一个实施的例子吗?

我的 activity 中的新权限检查已经开始工作(就像 Whosebug 上的一些示例所描述的那样),但是当我的服务执行所有 LocationUpdate 时它是如何工作的?

好的更新:这就像现在在我的 activity 中一样,但我仍然收到错误消息,因为我#m 只检查我的活动。我怎样才能让我的服务部分了解权限?

我的错误信息:

05-30 15:59:24.035 4261-4261/com.pekam E/Google APi Client﹕ Google APi Connected Failed. java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.

我的activity代码:

@Override
    protected void onStart() {
        super.onStart();
        loadPermissions(android.Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_FINE_LOCATION);
        if (com.pekam.util.MyAppSettings.isMyServiceRunning(MyService.class, this)) {
            Intent intent = new Intent(this, MyService.class);
            bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        } else {
            Intent intent = new Intent(this, MyService.class);
            startService(intent);
            bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        }
    }




private void loadPermissions(String perm,int requestCode) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) {
                ActivityCompat.requestPermissions(this, new String[]{perm},requestCode);
            }
        }
    }

服务class代码:

public class MyService  extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,LocationListener,AsyncDelegate {

    //CurrentUser Object with tracks & everything
    public static TblUser user = new TblUser();
    public static boolean dataRefresh=false;

    private IBinder mBinder = new MyBinder();


    private static final int REQUEST_FINE_LOCATION=0;

    private NotificationManager nm;
    private Timer timer = new Timer();


    private LocationRequest mLocationRequest = new LocationRequest();

    private String strLOG = "LOG";

    private InternetConnectionDetector cd ;
    private Boolean isInternetPresent;





    //GoogleApiClient
    private GoogleApiClient googleApiClient;
    @Override
    public void onLocationChanged(Location location) {
        Location mCurrentLocation = location;

        try {

            TblGps gps1 = new TblGps();
            gps1.setLat(mCurrentLocation.getLatitude());
            gps1.setLng(mCurrentLocation.getLongitude());
            gps1.setDate(new Timestamp(new Date().getTime()));
            gps1.setProvider(mCurrentLocation.getProvider());
            gps1.setDeviceID("1");

            user.getTracks().get(0).getTblgps().add(gps1);
            Log.i("onLocationChanged","new Lat:" + gps1.getLat() +", Lng:"+ gps1.getLng());
            Toast.makeText(this, "Location  new Location Added", Toast.LENGTH_SHORT).show();

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

    @Override
    public void onConnectionFailed(ConnectionResult bundle) {

    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.i("onConnected", "GoogleApiClient");
        try {
            Toast.makeText(this, "Location  service connected", Toast.LENGTH_SHORT).show();

            createLocationRequest();
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    googleApiClient, mLocationRequest, this);
            LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

        } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
            Log.e("Google APi Client", "Google APi Connected Failed.", t);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
    }

    //Service
    @Override
    public void onCreate() {
        super.onCreate();
        cd = new InternetConnectionDetector(getApplicationContext());
        isInternetPresent = cd.isConnectingToInternet();
        Log.i("MyService", "Service Started.");

        showNotification();

        getUserObject();

        timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                onTimerTick();
            }
        }, 60000, 19000L);

        try {
            googleApiClient = new GoogleApiClient.Builder(this)

                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)

                    .build();

            googleApiClient.connect();

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService", "Received start id " + startId + ": " + intent);
        return START_STICKY; // run until explicitly stopped.
    }

    @Override
    public void onDestroy() {
        SharedPreferences mPrefs;
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor prefsEditor = mPrefs.edit();
        Gson gson = new Gson();
        String json = gson.toJson(user);
        prefsEditor.putString("MyObject", json);
        prefsEditor.commit();
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    // Async Task delegate
    @Override
    public void executionFinished(HttpRequestTaskGetUser userTask) {
        String name= userTask.result.getName();
        Log.i("executionFinishedGet",name);
        Toast.makeText(this, "Location  executionFinishedGet", Toast.LENGTH_SHORT).show();

    }
    private void checkPermission() {
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

//            ActivityCompat.requestPermissions(this,
//                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION},
//                    REQUEST_FINE_LOCATION);

        } else {

        }
    }
    @Override
    public void executionFinished(HttpRequestTaskSaveUser userTask) {
        String name= userTask.result.getName();
        Log.i("executionFinishedSave", name );
        Toast.makeText(this, "Location  executionFinishedGet", Toast.LENGTH_SHORT).show();
    }
    private void getUserObject() {
         try {
            if (isInternetPresent){
                HttpRequestTaskGetUser  http = new HttpRequestTaskGetUser();
                http.delegate=this;
                http.execute(user);
                }

        } catch (Throwable t) {
            Log.e("getuserObject", "getuserObject Failed.", t);
        }
    }

    private void saveUserObject() {
        try {

        if (isInternetPresent) {
            HttpRequestTaskSaveUser http = new HttpRequestTaskSaveUser();
            http.delegate=this;
            http.execute(this.user);
        }
    } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
                    Log.e("saveUserObject", "saveUserObject Failed.", t);
           }
    }





    public boolean isRunning()
        {
            return isMyServiceRunning(this.getClass());
        }
    private void onTimerTick() {

            try {
                saveUserObject();
                Log.i("TimerTick", "Saved User." );
            } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
                Log.e("TimerTick", "Timer Tick Failed.", t);            
            }
        }
    private boolean isMyServiceRunning(Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
    private boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == status) {
            return true;
        } else {
          //  GooglePlayServicesUtil.getErrorDialog(status, t, 0).show();
            return false;
        }
    }
    private void showNotification() {
        nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.service_started);
        // Set the icon, scrolling text and timestamp

        Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TabBarActivity.class), 0);
        // Set the info for the views that show in the notification panel.
     //  notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);



        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                this);
        notification = builder.setContentIntent(contentIntent)
               .setSmallIcon(R.drawable.ic_launcher).setTicker(text)//.setWhen(java.util.)
                .setAutoCancel(true)//.setContentTitle(title)
                .setContentText(text).build();
        nm.notify(1, notification);

         //  notification.contentIntent.
        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
      //  nm.notify(R.string.service_started, notification);
    }
    private void createLocationRequest() {

        mLocationRequest.setInterval(20000);
        mLocationRequest.setFastestInterval(10000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        }

    public class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }
    }

为此,如果您的服务在检查权限之前启动将无法正常工作,那么您必须在服务启动之前进行检查

使用这个方法。这应该有效。

  1. 在 Oncreate() 上:

     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)   {
                    givePerMisson();
                } else {
                    requestIntent();
                }
    
  2. Add/Delete 根据您的需要:

     @TargetApi(Build.VERSION_CODES.M)
    private void givePerMisson() {
        if ((AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) &&
                AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.CALL_PHONE) &&
                AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) &&
                AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.GET_ACCOUNTS) &&
                AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) &&
                AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.CAMERA)
        )) {
            requestIntent();
        } else {
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION, AndyUtils.PERMISSOIN);
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.CALL_PHONE, AndyUtils.PERMISSOIN);
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, AndyUtils.PERMISSOIN);
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.ACCESS_FINE_LOCATION, AndyUtils.PERMISSOIN);
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.GET_ACCOUNTS, AndyUtils.PERMISSOIN);
            AndyUtils.givePermisson(SplashActivity.this, Manifest.permission.CAMERA, AndyUtils.PERMISSOIN);
            if (!AndyUtils.permissionsList.isEmpty()) {
                requestPermissions(AndyUtils.permissionsList.toArray(new String[AndyUtils.permissionsList.size()]), AndyUtils.PERMISSOIN_CODE);
            }
        }
    
    }
    

3.

 @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case AndyUtils.PERMISSOIN_CODE: {
            if ((AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) &&
                    AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.CALL_PHONE) &&
                    AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) &&
                    AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.GET_ACCOUNTS) &&
                    AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) &&
                    AndyUtils.checkPermission(SplashActivity.this, Manifest.permission.CAMERA)
            )) {
                requestIntent();
            } else {
                finish();
            }
        }
    }
}
  1.   public static boolean checkPermission(Context context, String permission) {
    try {
        PackageManager pm = context.getPackageManager();
        if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
        }
    
    } catch (Exception e) {
        Log.e("PermissionError", e.toString());
    }
    return false;
    }
    

    5.

    public static void givePermisson(Context context, String permisson, String permissonType) {
        int per = context.checkSelfPermission(permisson);
        if (per != PackageManager.PERMISSION_GRANTED) {
            permissionsList.add(permisson);
    
        } else if (per != PackageManager.PERMISSION_DENIED) {
        }
    }
    

是的,您可以在 activity 中接受一次权限并在服务中使用它,如果您授予权限,那么它将永远不会再询问。以下是 ACCESS_FINE_LOCATION 显示对话框的代码,您也可以参考 Requesting Permissions at Run Time

private void showPermissionDialog() {
    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(mActivity,
            Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
                Manifest.permission.ACCESS_FINE_LOCATION)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(mActivity,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_FOR_LOCATION);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } else {
        if (mGoogleApiClient != null)
            mGoogleApiClient.connect();
    }
}