5

我編寫了一個Android應用程序,使用DownloadManager將樣本PDF文件下載到下載目錄。下面的代碼:下載管理器Android權限錯誤:編寫外部存儲

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_vertretungsplan); 
    Button dlbutton = (Button) findViewById(R.id.buttondownload); 
    final Context c = this; 
    dlbutton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      DownloadManager.Request request = new DownloadManager.Request(Uri.parse(myurl)); 
      request.setTitle("Vertretungsplan"); 
      request.setDescription("wird heruntergeladen"); 
      request.allowScanningByMediaScanner(); 
      request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 
      String filename = URLUtil.guessFileName(myurl, null, MimeTypeMap.getFileExtensionFromUrl(myurl)); 
      request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); 
      DownloadManager manager = (DownloadManager) c.getSystemService(Context.DOWNLOAD_SERVICE); 
      manager.enqueue(request); 
     } 
    }); 
} 

現在,我試圖從Android的工作室在我的Xperia Z3的Android 6.0調試運行。 當我點擊下載按鈕,出現此錯誤:

E/AndroidRuntime: FATAL EXCEPTION: main 
       Process: com.example.markwitt.schul_app, PID: 29297 
       java.lang.SecurityException: No permission to write to /storage/emulated/0/Download/hrpsampletable.pdf: Neither user 10047 nor current process has android.permission.WRITE_EXTERNAL_STORAGE. 
        at android.os.Parcel.readException(Parcel.java:1627) 
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183) 
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135) 
        at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476) 
        at android.content.ContentResolver.insert(ContentResolver.java:1240) 
        at android.app.DownloadManager.enqueue(DownloadManager.java:946) 
        at com.example.markwitt.schul_app.Vertretungsplan$1.onClick(Vertretungsplan.java:59) 
        at android.view.View.performClick(View.java:5280) 
        at android.view.View$PerformClick.run(View.java:21239) 
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:224) 
        at android.app.ActivityThread.main(ActivityThread.java:5526) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

從目標VM,地址斷開連接:「本地主機:8600」,運輸:「插座」

(第三行),它向我顯示它對外部存儲沒有寫入權限。

但我AndroidManifest設置正確:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example.markwitt.schul_app"> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.INTERNET" /> 
<application 
    android:launchMode="singleTop" 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"> 

    <activity android:name=".Stundenplan"> 


     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <activity android:name=".Vertretungsplan"></activity> 
</application> 

什麼我需要做什麼?

+0

https:// stackoverflow。com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it – CommonsWare

回答

11

由於您的應用程序在Android 6.0(API等級23)中運行,因此出現此錯誤。從API級別> = 23您需要在運行時檢查權限。你的代碼是蠻好的下方水平23.所以,請先檢查你的用戶給予使用存儲的權限:

if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 
    Log.e("Permission error","You have permission"); 
    return true; 
} 

如果沒有,那麼提示要求:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); 

共有的東西看起來像這樣:

public boolean haveStoragePermission() { 
    if (Build.VERSION.SDK_INT >= 23) { 
     if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) 
       == PackageManager.PERMISSION_GRANTED) { 
      Log.e("Permission error","You have permission"); 
      return true; 
     } else { 

      Log.e("Permission error","You have asked for permission"); 
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); 
      return false; 
     } 
    } 
    else { //you dont need to worry about these stuff below api level 23 
     Log.e("Permission error","You already have the permission"); 
     return true; 
    } 
} 

而且過去的事:) 通過回調接收結果:

@Override 
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ 
      //you have the permission now. 
      DownloadManager.Request request = new DownloadManager.Request(Uri.parse(myurl)); 
      request.setTitle("Vertretungsplan"); 
      request.setDescription("wird heruntergeladen"); 
      request.allowScanningByMediaScanner(); 
      request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 
      String filename = URLUtil.guessFileName(myurl, null, MimeTypeMap.getFileExtensionFromUrl(myurl)); 
      request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); 
      DownloadManager manager = (DownloadManager) c.getSystemService(Context.DOWNLOAD_SERVICE); 
      manager.enqueue(request); 
     } 
    } 



或者,你可以使用我的自定義類PermissionCheck很輕鬆地處理這一切的實現。這裏是類:

import android.Manifest; 
import android.app.Activity; 
import android.content.Context; 
import android.content.pm.PackageManager; 
import android.support.v4.app.ActivityCompat; 

/** 
* Created by Tushar on 6/30/2017. 
*/ 

public class PermissionCheck{ 
    public static boolean readAndWriteExternalStorage(Context context){ 
     if(ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ 
      ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1); 
      return false; 
     }else{ 
      return true; 
     } 

    } 

    public static boolean audioRecord(Context context){ 
     if(ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED){ 
      ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.RECORD_AUDIO}, 2); 
      return false; 
     }else{ 
      return true; 
     } 

    } 

    public static boolean readAndWriteContacts(Context context){ 
     if(ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED){ 
      ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS}, 3); 
      return false; 
     }else{ 
      return true; 
     } 

    } 

    public static boolean vibrate(Context context){ 
     if(ActivityCompat.checkSelfPermission(context, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED){ 
      ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.VIBRATE}, 4); 
      return false; 
     }else{ 
      return true; 
     } 

    } 

    public static boolean sendSms(Context context){ 
     if(ActivityCompat.checkSelfPermission(context, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED){ 
      ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.SEND_SMS}, 5); 
      return false; 
     }else{ 
      return true; 
     } 

    } 

    //Just like this you can implement rest of the permissions. 
} 


用法:

if(PermissionCheck.readAndWriteExternalStorage(context)){ 
    //Your read write code. 
} 

if(PermissionCheck.sendSms(context)){ 
    //Your sms sending code. 
} 

**請注意,這些方法的調用將要求自動,也是你的onRequestPermissionsResult將被解僱的權限。 :)

+0

非常感謝你。 –

+0

你能告訴我字符串數組中的1是什麼意思嗎? –

+1

只是爲了防止任何人有問題與'Manifest.permission.WRITE_EXTERNAL_STORAGE'使用'android.manifest.permission.WRITE_EXTERNAL_STORAGE'而不是 –

0

我在我的API 23模擬器(24和25做得很好)上運行自定義標籤應用程序有這個相同的問題。我嘗試了這個解決方案以及其他一些變體,我可以看到我獲得了許可,但問題仍然存在於任何下載嘗試中。 當我在真實設備上運行應用程序(無權限請求代碼)時,系統會自動提示我允許Google訪問存儲 - 而不是我的應用程序。 我刪除了運行時權限的代碼,並設置了瀏覽器權限(模擬器上的默認值)來訪問存儲,我的應用程序工作正常。 以下文章提供了對模擬器可能發生的情況的一些瞭解:Requesting and allowing WRITE_EXTERNAL_STORAGE permission at runtime has no effects on the current session