在广播接收器上,检查是否具有android M的写入权限 [英] On broadcast receiver, check for write permission android M

查看:102
本文介绍了在广播接收器上,检查是否具有android M的写入权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用媒体文件夹android.hardware.action.NEW_PICTURE服务的broadcastreceiver使用以下代码重命名和移动图像,并且该图像正在运行:

I use broadcastreceiver of media folder android.hardware.action.NEW_PICTURE service to rename and move image using this code and it was running:

CameraReciver 包perim.ebrahimi.ir.perim;

CameraReciver package perim.ebrahimi.ir.perim;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;

public class CameraReciver extends BroadcastReceiver {

    private States states;
    private SessionManager session;
    private WriteService main;

    @Override
    public void onReceive(Context context, Intent intent) {
        getStates(context);
        if(states.getAPP()){

            Cursor cursor = context.getContentResolver().query(intent.getData(), null, null, null, null);
            cursor.moveToFirst();
            if(cursor!=null){
                String image_path = cursor.getString(cursor.getColumnIndex("_data"));
                main = new WriteService();
                main.writeFolder(image_path, states, context);
            }
            cursor.close();
        } else abortBroadcast();
    }

    // OK
    private void getStates(Context context){
        session = new SessionManager(context.getApplicationContext());
        states = new States();
        states = session.getSession();
    }

}

,这里是WriteService:

package perim.ebrahimi.ir.perim;

import android.app.Activity;
import android.app.Application;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class WriteService extends Activity {

    private States states;
    private Context context;
    private static CalendarJalalian cal;
    private static int day   ;
    private static int month ;
    private static int year  ;
    private static int saat  ;
    private static int minut ;
    private static int secnd ;
    private int orientation = -1;
    private static final int REQUEST_EXTERNAL_STORAGE = 100;
    private static final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS=200;
    private boolean mExternalStorageAvailable = false;
    private boolean mExternalStorageWriteable = false;

//    @Override
//    protected void onCreate(Bundle savedInstanceState) {
//        super.onCreate(savedInstanceState);
//        //setContentView(R.layout.activity_main);
//
//        // A simple check of whether runtime permissions need to be managed
//        if (Build.VERSION.SDK_INT >= 23) {
//            checkMultiplePermissions();
//        }
//    }

    public void writeFolder(String image_path, States _states, Context _context){
        states = _states;
        context=  _context;
        cal = new CalendarJalalian();
        long fileSize = new File(image_path).length();
        Cursor mediaCursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] {MediaStore.Images.ImageColumns.ORIENTATION,
                        MediaStore.MediaColumns.SIZE },
                MediaStore.MediaColumns.DATE_ADDED + ">=?",
                new String[]{String.valueOf(cal.getTimeInMillis()/1000 - 1)},
                MediaStore.MediaColumns.DATE_ADDED + " desc");
        if (mediaCursor != null && mediaCursor.getCount() !=0 ) {
            while(mediaCursor.moveToNext()){
                long size = mediaCursor.getLong(1);
                if(size == fileSize){
                    orientation = mediaCursor.getInt(0);
                    break;
                }
            }
        }
        orientation = (orientation<0)?0:orientation;
        image_path = changeName(image_path);
        if(image_path.length()==0) return;
        String image_jadid = copyFile(image_path);
        if(states.getMain() && image_jadid.length()>0){
            removeMain(image_path);
            removeMedia(context, new File(image_path));
        }
        if(states.getPayam()) Toast.makeText(this, getText(R.string.imageSaved)+": "+states.getKhas(), 500).show();

    }

    private void checkExternalStorage(){
        String[] aaa = new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
        ActivityCompat.requestPermissions(this, aaa , REQUEST_EXTERNAL_STORAGE);
        if(ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE);
        } else {
            String state = Environment.getExternalStorageState();
            if (Environment.MEDIA_MOUNTED.equals(state)) {
                mExternalStorageAvailable = mExternalStorageWriteable = true;
            } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
                mExternalStorageAvailable = true;
                mExternalStorageWriteable = false;
            } else {
                mExternalStorageAvailable = mExternalStorageWriteable = false;
            }
        }
    }

    private static void removeMedia(Context context, File f) {
        ContentResolver resolver = context.getContentResolver();
        resolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DATA + "=?", new String[] { f.getAbsolutePath() });
    }

    // OK
    private String changeName(String image_path){
        String result = "";
        day   = cal.getDay();
        month = cal.getMonth();
        year  = cal.getYear();
        saat  = Integer.parseInt(cal.getHHour());
        minut = Integer.parseInt(cal.getMinute());
        secnd = Integer.parseInt(cal.getSecond());

        String persianDateName = String.format("%1$s_%2$s_%3$s__%4$s_%5$s_%6$s.jpg",
                year,
                ((month<10)?"0"+month:month),
                ((day<10)?"0"+day:day),
                ((saat<10)?"0"+saat:saat),
                ((minut<10)?"0"+minut:minut),
                ((secnd<10)?"0"+secnd:secnd));

        File from = new File(image_path);
        if(from.exists()){
            if(states.getOnimage()){
                addTextToImage(image_path, persianDateName);
            }
            File to = new File(from.getParentFile(),persianDateName);
            try
            {
                boolean b = from.renameTo(to);
                if (!b) {
                    copy(from, to);
                    from.delete();
                }
                removeMedia(context, from);
                sendToMedia(to, persianDateName);
                result = to.getAbsolutePath();
            }
            catch(Exception ex){
                ex.printStackTrace();
            }
        }
        return result;
    }

    private void addTextToImage(String from, String persianDateName) {
        Log.i("info","Draw "+persianDateName+" on image");
        try
        {
            Log.i("info","1");
            FileOutputStream fos = new FileOutputStream(from);
            if(fos==null) Log.i("info","fos = null");

            Log.i("info","2 = "+from);
            Bitmap bitmap = BitmapFactory.decodeFile(from);
            if(bitmap==null) Log.i("info","bitmap = null");

//          Log.i("info","3");
            android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
            if(bitmapConfig==null) Log.i("info","bitmapConfig = null");

//          Log.i("info","4");
//          if (bitmapConfig == null) {
//              bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
//          }

            Log.i("info","5");
            bitmap = bitmap.copy(bitmapConfig, true);

            Log.i("info","6");
            Canvas canvas = new Canvas(bitmap);

            Log.i("info","7");
            Resources resources = this.getResources();
            float scale = resources.getDisplayMetrics().density;

            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.rgb(61, 61, 61));
            paint.setTextSize((int) (14 * scale));
            paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
            Rect qab = new Rect();
            paint.getTextBounds(persianDateName, 0, persianDateName.length(), qab);
            int x = (bitmap.getWidth() - qab.width()) / 2;
            int y = (bitmap.getHeight() + qab.height()) / 2;
            canvas.drawText(persianDateName, x, y, paint);

            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        Log.i("info","Text added on image");
    }

    private void copy(final File f1, final File f2) throws IOException {
        if(f2.exists()) f2.delete();
        //checkExternalStorage();
        checkMultiplePermissions();
        if(mExternalStorageAvailable && mExternalStorageWriteable) {
            f2.createNewFile();
            final RandomAccessFile file1 = new RandomAccessFile(f1, "r");
            final RandomAccessFile file2 = new RandomAccessFile(f2, "rw");
            file2.getChannel().write(file1.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length()));
            file1.close();
            file2.close();
        }
    }

    private boolean canRename(final File f1, final File f2) {
        final String p1 = f1.getAbsolutePath().replaceAll("^(/mnt/|/)", "");
        final String p2 = f2.getAbsolutePath().replaceAll("^(/mnt/|/)", "");
        return p1.replaceAll("\\/\\w+", "").equals(p2.replaceAll("\\/\\w+", ""));
    }

    // OK
    private void removeMain(String image_path){
        File f = new File(image_path);
        if(f.exists()) f.delete();
    }


    // OK
    private File createFileName(){
        day   = cal.getDay();
        month = cal.getMonth();
        year  = cal.getYear();
        saat  = Integer.parseInt(cal.getHHour());
        minut = Integer.parseInt(cal.getMinute());
        secnd = Integer.parseInt(cal.getSecond());

        String persianDateName = String.format("%1$s_%2$s_%3$s__%4$s_%5$s_%6$s.jpg",
                year,
                ((month<10)?"0"+month:month),
                ((day<10)?"0"+day:day),
                ((saat<10)?"0"+saat:saat),
                ((minut<10)?"0"+minut:minut),
                ((secnd<10)?"0"+secnd:secnd));

        String masirFolder = "";

        if(states.getSal())   masirFolder += year;
        if(states.getMah())   masirFolder += File.separator+ year+"_"+((month<10)?"0"+month:month);
        if(states.getRuz())   masirFolder += File.separator+ year+"_"+((month<10)?"0"+month:month)+"_"+((day<10)?"0"+day:day);

        if(states.getSaat())  masirFolder += File.separator+ year+"_"+((month<10)?"0"+month:month)+"_"+((day<10)?"0"+day:day)+"_"+((saat<10)?"0"+saat:saat);
        if(states.getMinut()) masirFolder += File.separator+ year+"_"+((month<10)?"0"+month:month)+"_"+((day<10)?"0"+day:day)+"_"+((saat<10)?"0"+saat:saat)+"_"+((minut<10)?"0"+minut:minut);

        if(states.getKhas().length()>0) masirFolder += File.separator+states.getKhas();

        File directTime = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), masirFolder);

        if (!directTime.mkdir()) makeDir(directTime);

        directTime = new File(directTime, persianDateName);

        return directTime;

    }

    // OK
    private void makeDir(File direct){
        direct.mkdirs();
    }

    // OK
    private String copyFile(String image_path){
        String masir = "";
        File sourceFile = new File(image_path);
        if (!sourceFile.exists()) {return masir;}
        File destinationFile = createFileName();
        FileChannel source = null;
        FileChannel destination = null;

        try {
            source = new FileInputStream(sourceFile).getChannel();
            destination = new FileOutputStream(destinationFile).getChannel();
            if (destination != null && source != null) {
                destination.transferFrom(source, 0, source.size());
            }
            if (source != null) {
                source.close();
            }
            if (destination != null) {
                destination.close();
            }
            masir = destinationFile.getName();
            sendToMedia(destinationFile, masir);
            masir = destinationFile.getAbsolutePath();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return masir;
    }

    // OK
    private void sendToMedia(File imageFile, String imageTitle){
        ContentValues image = new ContentValues();
        Date dateTaken = new Date();

        File parent = imageFile.getParentFile();
        String path = parent.toString().toLowerCase();
        String name = parent.getName().toLowerCase();

        image.put(MediaStore.Images.Media.TITLE, imageTitle);
        image.put(MediaStore.Images.Media.DISPLAY_NAME, String.format(this.getText(R.string.imageDisplayName).toString(),states.getKhas()));
        image.put(MediaStore.Images.Media.DESCRIPTION, String.format(this.getText(R.string.imageDescription).toString(),name));
        image.put(MediaStore.Images.Media.DATE_ADDED, dateTaken.toString());
        image.put(MediaStore.Images.Media.DATE_TAKEN, dateTaken.toString());
        image.put(MediaStore.Images.Media.DATE_MODIFIED, dateTaken.toString());
        image.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
        image.put(MediaStore.Images.Media.ORIENTATION, orientation);//getImageOrientation(imageFile.getAbsolutePath()));

        image.put(MediaStore.Images.ImageColumns.BUCKET_ID, path.hashCode());
        image.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
        image.put(MediaStore.Images.Media.SIZE, imageFile.length());
        image.put(MediaStore.Images.Media.DATA, imageFile.getAbsolutePath());

        this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
    }

    private void checkMultiplePermissions() {

        if (Build.VERSION.SDK_INT >= 23) {
            List<String> permissionsNeeded = new ArrayList<String>();
            List<String> permissionsList = new ArrayList<String>();

            if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
                permissionsNeeded.add("GPS");
            }

            if (!addPermission(permissionsList, android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
                permissionsNeeded.add("Read Storage");
            }

            if (permissionsList.size() > 0) {
                requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                        REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                return;
            }
        }
    }

    private boolean addPermission(List<String> permissionsList, String permission) {
        try {
            if (Build.VERSION.SDK_INT >= 23)

                if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                    permissionsList.add(permission);

                    if (!shouldShowRequestPermissionRationale(permission))
                        return false;
                }
        } catch(Exception ex){
            ex.printStackTrace();
        }
        return true;
    }
}

但是类addPermission引发错误:

But class addPermission raise error:

java.lang.NullPointerException:尝试调用虚拟方法'int android.content.Context.checkSelfPermission(java.lang.String)' 空对象引用

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Context.checkSelfPermission(java.lang.String)' on a null object reference

我认为我所说的活动方式不正确,但是我不知道该怎么做,请帮忙.

I think the way I call activity is not correct, but I have no idea how to do it, please help.

我在返回的路径中发现了这种差异:

I have found this difference in returned path:

String image_path = cursor.getString(cursor.getColumnIndex("_data"));

更改的部分很明显:

old but correct path: /storage/emulated/0/DCIM/Camera/IMG_20161215_173334.jpg
new but incorrect path: /storage/3466-033/DCIM/Camera/IMG_20161215_173334.jpg

我认为由于新设备允许用户选择保存图像的位置,因此返回地址也会相应更改. 如何从游标中获取正确的地址?

I think since new devices permit user to select where to save Images, then returning address is changed accordingly. How to get correct address out of cursor?

推荐答案

您不能使用广播接收器来做到这一点.您可以通过

You can't do that with a broadcast receiver. You can check if you have a permission via ContextCompat.checkSelfPermission, but in order to request the permission, you need to call ActivityCompat.requestPermissions. It needs an activity, and the result will also arrive to that activity.

鉴于此,最适合您的解决方案是实施一些活动,该活动将向用户解释发生了什么并请求许可.如果广播接收方检测到没有必要的权限,它将启动此活动.授予权限后,将恢复正常操作.

Given that, the best solution for you is to implement some activity which will explain the user what is going on and request the permission. If the broadcast receiver detects that it doesn't have the necessary permission, it would launch this activity. When the permission is granted, the normal operation would be resumed.

我必须说,作为用户,如果突然弹出带有权限请求的对话框,这对我来说很奇怪,所以我认为最好是您需要一个活动来请求权限

I have to say that as a user it would be very weird to me if a dialog with a permission request suddenly popped up out of the blue, so I think it's for the best that you need to have an activity to request permissions.

但是,从您的路径来看,它肯定在SD卡上的某个位置.这意味着将应用SD卡写入限制.这意味着请求写权限将无济于事.看看这个问题:?

Judging by your path, however, it is definitely somewhere on the SD card. This means that the SD card write restrictions apply. That means that requesting permissions for writing won't help. Take a look at this question: How to avoid the "EACCES permission denied" on SD card?

这篇关于在广播接收器上,检查是否具有android M的写入权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆