How to check new android 6.0 Permissions from service

时间秒杀一切 提交于 2019-12-31 03:47:08

问题


I've an Android 6.0 Application with an unbound android service connecting to Google API for receiving Fused API Location Provider Updates. For this i need the ACCESS_FINE_LOCATION Permission. Everthing was working fine untill the Update to Marshmallow. Now I need to implement the new Permission Model for my App.

I've read that it is not possible to check android 6.0 Permissions directly from within a service.

All of my Location Update Receiver and Google APi Client connect part is handled by and in the service, and I would linke to keep it there!

Is it possible to check the Permissions once in the acivity and then handle it over to the service when the service is started and the permissions stay in the service for lifetime of the service? Or do I have to check permissions on every LocationUpdate?

And how excactly can I implement the permission check for my service? Has anybody done it yet? Can you give me an Example of your Implementation?

The new Permission check in my activity is already working (like descibed by some examples here on StackOverflow), but how does it work when my service is doing All of the LocationUpdate?

ok update: this is like it is now in my activity but i still receive an error because I#m only checking within my acitvity. How can I get my service part to get aware of the permissions?

my error message:

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.

my activity code:

@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);
            }
        }
    }

service class code:

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:


Yes you can accept the permissions once in activity and use it in service , if you grant the permission , then it will never ask again. Following is the code for showing dialog for ACCESS_FINE_LOCATION ,You can also refer 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();
    }
}



回答2:


For that you have to check before your service start if your service start before checking permission will not work properly




回答3:


Use this method. This should work.

  1. On Oncreate() :

     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)   {
                    givePerMisson();
                } else {
                    requestIntent();
                }
    
  2. Add/Delete as per your need:

     @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) {
        }
    }
    


来源:https://stackoverflow.com/questions/37539187/how-to-check-new-android-6-0-permissions-from-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!