2016-12-14 7 views
0

я использую BroadcastReceiver медиа службы папки android.hardware.action.NEW_PICTURE переименовывать и перемещать изображение, используя этот код и он работает:На радиовещательного приемника, проверьте разрешения на запись андроида M

CameraReciver пакет Перим .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 рейз

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

Я думаю, как я называю деятельность не является правильным, но я понятия не имею, как это сделать, пожалуйста, помогите.

Edit: Я нашел эту разницу в возвращенном пути:

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 

Я думаю, так как новый пользователь разрешения устройств для выбора места для сохранения изображений, то соответственно изменяется адрес возврата. Как получить правильный адрес из курсора?

+0

Измените свой вопрос и покажите всю трассировку стека Java, связанную с вашим исключением. – CommonsWare

+0

Достаточно htis: java.io.IOException: open failed: EACCES (Permission denied) –

ответ

0

Вы не можете сделать это с помощью широковещательного приемника. Вы можете проверить, есть ли у вас разрешение через ContextCompat.checkSelfPermission, но для того, чтобы запросить разрешение, вам необходимо позвонить ActivityCompat.requestPermissions. Ему нужна деятельность, и результат также придет к этой деятельности.

Учитывая, что лучшим решением для вас является реализация какой-либо деятельности, которая объяснит пользователю, что происходит и запрашивает разрешение. Если широковещательный приемник обнаруживает, что у него нет необходимого разрешения, он запускает это действие. Когда разрешение будет предоставлено, нормальная операция будет возобновлена.

Я должен сказать, что для меня было бы очень странно, если бы диалоговое окно с запросом разрешения внезапно появилось неожиданно, поэтому я думаю, что для вас лучше всего иметь требуемую активность разрешения.

Судя по вашему пути, однако, это определенно где-то на SD-карте. Это означает, что применяются ограничения на запись SD-карты. Это означает, что запрашивающие разрешения на запись не помогут. Взгляните на этот вопрос: How to avoid the “EACCES permission denied” on SD card?

+0

Вы правы, обычно в broadcastreceiver невозможно запросить разрешение, хотя есть способ запросить разрешение на основе внешней активности ;; но в этом случае, когда я проверяю, он говорит, что у него есть разрешение, он говорит, что sdcard настроен, и я могу писать, также как исходная, так и папка-хранилище одинаковы. –

+0

@AhmadEbrahimi Ах, так это SD-карта, на которую вы пишете. Затем взгляните на этот вопрос: [Как избежать отклонения разрешения EACCES на SD-карте?] (Http://stackoverflow.com/questions/22406061/howto-avoid-the-eacces-permission-denied-on- sdcard-with-kitkat-4-4-2-version) – Malcolm

+0

Звучит так, что я допустил ошибку: File (Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DCIM), masirFolder) это не SdCard –