Android के लिए READ_EXTERNAL_STORAGE अनुमति


84

मैं उन्हें चलाने के लिए उपयोगकर्ता डिवाइस पर मीडिया फ़ाइलों (संगीत) का उपयोग करने की कोशिश कर रहा हूं; एक आसान "हैलो वर्ल्ड" -म्यूजिक प्लेयर ऐप।

मैंने कुछ ट्यूटोरियल्स का अनुसरण किया है और वे मूल रूप से समान कोड देते हैं। लेकिन यह काम नहीं करेगा; यह दुर्घटनाग्रस्त रहता है और मुझे बताता है:

error.....
Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=27696, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
....

अब, यह मेरी मैनिफ़ेस्ट फ़ाइल है:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="slimsimapps.troff" >

    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

यह मेरी जावा-विधि है:

public void initialize() {
    ContentResolver contentResolver = getContentResolver();
    Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor cursor = contentResolver.query(uri, null, null, null, null);
    if (cursor == null) {
        // query failed, handle error.
    } else if (!cursor.moveToFirst()) {
        // no media on the device
    } else {
        do {
            addSongToXML(cursor);
        } while (cursor.moveToNext());
    }
}

मैंने कोशिश की है:

इसे मैनिफ़ेस्ट फ़ाइल में विभिन्न स्थानों पर रखने के लिए:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE”/>

Android जोड़ने के लिए: maxSdkVersion पर बाहरी संग्रहण पढ़ें पढ़ें:

<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="21" />

इसे प्रकट / आवेदन / गतिविधि-टैग में डालने के लिए:

android:exported=“true

Javamethod में uri और सरसो के बीच अनुदानप्राप्ति करना:

grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

इसका उपयोग करने के लिए, यह क्रैश नहीं होगा, लेकिन कर्सर शून्य हो जाता है:

uri = MediaStore.Audio.Media.getContentUri("EXTERNAL_CONTENT_URI”);

आंतरिक सामग्री यूरी का उपयोग करने के लिए, यह उम्मीद के मुताबिक काम करता है, लेकिन यह केवल "ओएस-साउंड" देता है जैसे शटर-साउंड, लो-बैटरी-साउंड, बटन-क्लिक और जैसे:

uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;

दलीलों की मदद, यह एक कठिन समस्या नहीं होनी चाहिए जिसे मैं जानता हूं, लेकिन मुझे ऐसा लगता है!

मैंने पढ़ा है और कोशिश की है (या उन्हें मेरी समस्या के लिए लागू नहीं माना जाता है):

स्टैक ट्रेस:

09-08 06:59:36.619    2009-2009/slimsimapps.troff D/AndroidRuntime﹕ Shutting down VM
    --------- beginning of crash
09-08 06:59:36.619    2009-2009/slimsimapps.troff E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: slimsimapps.troff, PID: 2009
    java.lang.IllegalStateException: Could not execute method for android:onClick
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4452)
            at android.view.View.performClick(View.java:5198)
            at android.view.View$PerformClick.run(View.java:21147)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5417)
            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)
     Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
            at android.view.View.performClick(View.java:5198)
            at android.view.View$PerformClick.run(View.java:21147)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5417)
            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)
     Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=2009, uid=10059 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
            at android.os.Parcel.readException(Parcel.java:1599)
            at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
            at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
            at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
            at android.content.ContentResolver.query(ContentResolver.java:491)
            at android.content.ContentResolver.query(ContentResolver.java:434)
            at slimsimapps.troff.MainActivity.initialize(MainActivity.java:106)
            at slimsimapps.troff.MainActivity.InitializeExternal(MainActivity.java:80)
            at java.lang.reflect.Method.invoke(Native Method)
            at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
            at android.view.View.performClick(View.java:5198)
            at android.view.View$PerformClick.run(View.java:21147)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:148)
            at android.app.ActivityThread.main(ActivityThread.java:5417)
            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)
    --------- beginning of system

उस त्रुटि को दिखाया गया है जब आपने यह लाइन प्रकट में उपयोग नहीं की है <उपयोग-अनुमति एंड्रॉइड: नाम = "android.permission.READ_EXTERNAL_STORAGE" /> क्या आप कुछ फ़ाइलों को पढ़ने की कोशिश कर रहे हैं जो कुछ अन्य ऐप्स द्वारा संरक्षित है?
सुनील

आप किस एपीआई स्तर पर यह कोशिश कर रहे हैं?
शार्प एज

क्या आपने प्रोजेक्ट को साफ करने की कोशिश की। ?
धूप

@sunilsunny मैं उन सो फाइल्स को पढ़ने की कोशिश नहीं कर रहा हूं जो संरक्षित हैं, ऐसा नहीं है कि मुझे वैसे भी पता है, सिर्फ एक साधारण मीडिया प्लेयर। हां, मैंने इसे साफ करने की कोशिश की है, मैंने कंप्यूटर को फिर से शुरू करने की कोशिश की है, मैंने एक हस्ताक्षरित एपीके जनरेट करने की कोशिश की है और इसे Google Play पर प्रकाशित किया है और इसे एक परीक्षक के रूप में एक्सेस किया है, जिसमें कोई भाग्य नहीं है ...
स्लिम सिम

@तेज धार ; मेरे AVD मानक नेक्सस 5 है, एपीआई 23. मेरे मॉड्यूल Gradle है: compileSdkVersion 23 buildToolsVersion "23.0.0" minSdkVersion 14 targetSdkVersion 23 तो मैं कहूंगा कि 23
स्लिम सिम

जवाबों:


90

आपकी समस्या के लिए आपके पास दो समाधान हैं। त्वरित एक लक्ष्य एएपीआई को घटाकर 22 (बिल्ड.ग्रेडल फाइल) कर रहा है। दूसरा है नए और अद्भुत आस्क-फॉर-परमिशन मॉडल का उपयोग करना:

if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_EXTERNAL_STORAGE)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);

    // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
    // app-defined int constant that should be quite unique

    return;
}

स्निपलेट यहां पाया गया: https://developer.android.com/training/permissions/requesting.html

समाधान 2: यदि यह काम नहीं करता है तो यह कोशिश करें:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
        REQUEST_PERMISSION);

return;

}

और फिर कॉलबैक में

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION) {
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // Permission granted.
    } else {
        // User refused to grant permission.
    }
}
}

टिप्पणियों से है। धन्यवाद


1
हां बिल्कुल! नए अनुमति मॉडल Google ने नवीनतम एंड्रॉइड के साथ पेश किया! धन्यवाद, मैं जितनी जल्दी हो सके इस का परीक्षण करूंगा और अगर यह काम करता है तो इसे सही चिह्नित करेगा! (और मुझे लगता है कि यह भूल गया था शुरू कर रहा था!)
स्लिम सिम

1
जो अनुमति मांगी जा रही है वह होनी चाहिए READ_EXTERNAL_STORAGE। जैसे इस उत्तर में
मैकलियर

स्वैप! = PackageManager.READ_EXTERNAL_STORAGE के लिए! = PackageManager.PERMISSION_GRANTED
रेनसेंज़ा

1
@ रेनासिंज़ा, हाँ आप सही हैं। किसी ने इस उत्तर को गलत तरीके से संपादित किया।
पोट्ट्रपो

2
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE क्या है?
सोलो

17

आपको रन टाइम पर अनुमति मांगनी होगी:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_PERMISSION);
    dialog.dismiss();
    return;
}

और नीचे कॉलबैक में आप बिना किसी समस्या के स्टोरेज तक पहुँच सकते हैं।

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission granted.
        } else {
            // User refused to grant permission.
        }
    }
}

7

चरण 1: Android मैनिफ़ेस्ट.xml पर अनुमति जोड़ें

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Step2: onCreate () विधि

int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_MEDIA);
    } else {
        readDataExternal();
    }

चरण 3: कॉलबैक पाने के लिए onRequestPeaksResult विधि को ओवरराइड करें

 @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_MEDIA:
            if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                readDataExternal();
            }
            break;

        default:
            break;
    }
}

नोट: readDataExternal () बाहरी संग्रहण से डेटा प्राप्त करने की विधि है।

धन्यवाद।


1
मुझे लगता है कि आपने यहां आवश्यक अनुमति को गलत कर दिया है: READ_EXTERNAL_STORAGE।
रेन्नासियाज़ा

4

मेरे पास भी एक समान त्रुटि लॉग था और यहां मैंने क्या किया-

  1. ऑनक्रीट विधि में हम अनुमतियों की जांच के लिए एक डायलॉग बॉक्स का अनुरोध करते हैं

    ActivityCompat.requestPermissions(MainActivity.this,
    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
    
  2. परिणाम के लिए जाँच करने की विधि

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission granted and now can proceed
             mymethod(); //a sample method called
    
            } else {
    
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        // add other cases for more permissions
        }
    }
    

अनुरोध करने के लिए आधिकारिक दस्तावेज अनुमतियाँ अनुमतियाँ


1
मैं इसे इस्तेमाल किया और यह पूरी तरह से काम किया यह सभी Android उपकरणों पर काम करता है?
महदी हरेबी

1

क्या आपकी समस्या का समाधान हो चुका है? आपका लक्ष्य SDK क्या है? को जोड़ने android;maxSDKVersion="21"का प्रयास करें<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


कोर्डोवा का उपयोग करके मेरे लिए काम किया, AndroidManifest.xml में केवल अधिकतम एसडीके संस्करण 22 (23 के बजाय) पर सेट करके
जॉर्ज कगन

0

http://developer.android.com/reference/android/provider/MediaStore.Audio.AudioColumns.html

लाइन बदलने की कोशिश करें contentResolver.query

//change it to the columns you need
String[] columns = new String[]{MediaStore.Audio.AudioColumns.DATA}; 
Cursor cursor = contentResolver.query(uri, columns, null, null, null);

सार्वजनिक स्थिर अंतिम स्ट्रिंग MEDIA_CONTENT_CONTROL

मीडिया की खपत की गोपनीयता के कारण तृतीय-पक्ष एप्लिकेशन द्वारा उपयोग के लिए नहीं

http://developer.android.com/reference/android/Manifest.permission.html#MEDIA_CONTENT_CONTROL

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>पहले को हटाने का प्रयास करें और फिर से प्रयास करें?


धन्यवाद, मैंने आपके सुझाव की कोशिश की लेकिन यह उसी जगह दुर्घटनाग्रस्त हो गया ... मैं एक मैक का उपयोग कर रहा हूं, क्या यह समस्या हो सकती है?
स्लिम सिम

अपडेट किया गया, निकालने <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>का प्रयास करें और कोशिश करें? यह अजीब व्यवहार पैदा कर सकता है क्योंकि आपके ऐप के अनुरोध की अनुमति नहीं है
डेरेक फंग

धन्यवाद, मैं उस अनुमति को हटाने की कोशिश की, लेकिन यह एक ही त्रुटि के साथ एक ही स्थान पर दुर्घटनाग्रस्त हो जाता है ...
स्लिम सिम

0

कृपया नीचे दिए गए कोड की जाँच करें, जिसका उपयोग करके आप sdcard से सभी संगीत फ़ाइलें पा सकते हैं:

public class MainActivity extends Activity{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_animations);
    getAllSongsFromSDCARD();

}

public void getAllSongsFromSDCARD() {
    String[] STAR = { "*" };
    Cursor cursor;
    Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";

    cursor = managedQuery(allsongsuri, STAR, selection, null, null);

    if (cursor != null) {
        if (cursor.moveToFirst()) {
            do {
                String song_name = cursor
                        .getString(cursor
                                .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
                int song_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media._ID));

                String fullpath = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.DATA));

                String album_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM));
                int album_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));

                String artist_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST));
                int artist_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));
                System.out.println("sonng name"+fullpath);
            } while (cursor.moveToNext());

        }
        cursor.close();
    }
}


}

मैंने नीचे दिए गए AndroidManifest.xml फ़ाइल में निम्न पंक्ति भी जोड़ी है:

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

धन्यवाद, मैंने पहले भी कुछ इसी तरह की कोशिश की है, लेकिन मैंने आपके कोड की कोशिश की और यह "कर्सर = मैनेज्ड (allsongsuri, STAR, चयन, अशक्त, अशक्त)" पर क्रैश कर दिया, "पहले की तरह ही त्रुटि। वैसे; प्रबंधित किया गया है पदावनत, लेकिन यह अभी भी दुर्घटनाग्रस्त हो जाता है यदि मैं इसे "contentResolver.query" में बदल देता हूं, जिसमें समान इनपुट पैरामीटर हैं ...
स्लिम सिम

नमस्ते मैं उपरोक्त कोड का उपयोग करके सभी sdcadr गाने प्राप्त करने में सक्षम हूं। Android संस्करण 4.2.2 डिवाइस के साथ और संस्करण 5.0.2 के साथ भी सक्षम है। जिसमें आप प्रयास कर रहे हैं। एंड्रॉइड वर्जन के साथ आपको क्या त्रुटि हुई, कृपया बताएं
राजन भावसार

मैंने स्टैक-ट्रेस के साथ प्रश्न को अपडेट किया है, आशा है कि मदद करता है। Android संस्करण के साथ आपका क्या मतलब है? (मैं apk 23 का उपयोग कर रहा हूं)
स्लिम सिम

ठीक है, मुझे पूर्ण स्रोत कोड दें और फिर से देखें।
राजन भावसार

यदि आप अपने लिए परीक्षण करना चाहते हैं, तो यहां ज़िप डाउनलोड करें: drive.google.com/open?id=0B2AV8VRk9HUeVzFXSWVRZU9TRUk जब आप इसे चलाते हैं, तो बचे इनिशियलाइज़-बटन को दबाएं, क्रेच उत्पन्न करने के लिए।
स्लिम सिम

0

सभी उत्तरों के अलावा। आप इस एनोटेशन के साथ आवेदन करने के लिए minsdk भी निर्दिष्ट कर सकते हैं

@TargetApi(_apiLevel_)

मैंने इस अनुरोध को स्वीकार करने के लिए इसका उपयोग किया यहां तक ​​कि मेरा minsdk 18 है। यह क्या करता है कि विधि केवल तभी चलती है जब डिवाइस "_apilevel_" और ऊपरी को लक्षित करता है। यहाँ मेरी विधि है:

    @TargetApi(23)
void solicitarPermisos(){

    if (ContextCompat.checkSelfPermission(this,permiso)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (shouldShowRequestPermissionRationale(
                Manifest.permission.READ_EXTERNAL_STORAGE)) {
            // Explain to the user why we need to read the contacts
        }

        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                1);

        // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
        // app-defined int constant that should be quite unique

        return;
    }

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.