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