2017-07-12 25 views
1

我試圖構建一個應用程序,該應用程序在給定url時從web下載文件(例如「.jpg」,「.txt」)。它並不真正意味着成爲真正的世界應用程序,更多的只是一個練習,以幫助我更好地使用基於網絡和基於io的代碼。現在我只是從url中提取字節,然後將它們轉換爲字符串並記錄下來。然後從那裏我想寫這個文件。我現在遇到了問題是,即時得到一個文件未發現異常,說明訪問被拒絕:當試圖從web到文件寫入字符串時,FileNotFoundException(權限)

07-11 21:03:14.458 19072-20051/com.example.zacharymcdaniel.webdownloader E/AsyncDownload: network errorjava.io.FileNotFoundException: /sdcard/-1157023572 (Permission denied) 
                         java.io.FileNotFoundException: /sdcard/-1157023572 (Permission denied) 
                          at java.io.FileOutputStream.open(Native Method) 
                          at java.io.FileOutputStream.<init>(FileOutputStream.java:221) 
                          at java.io.FileOutputStream.<init>(FileOutputStream.java:169) 
                          at com.example.zacharymcdaniel.webdownloader.AsyncDownload.doInBackground(AsyncDownload.java:60) 
                          at com.example.zacharymcdaniel.webdownloader.AsyncDownload.doInBackground(AsyncDownload.java:23) 
                          at android.os.AsyncTask$2.call(AsyncTask.java:304) 
                          at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                          at java.lang.Thread.run(Thread.java:761) 

這裏是我的清單:

<?xml version="1.0" encoding="utf-8"?> 

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

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

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

以及我用於執行下載和寫入操作的asynctask實現的代碼:

public class AsyncDownload extends AsyncTask<Void, Void, Void>{ 
private static final String TAG = "AsyncDownload"; 
private static final String STORAGE_LOCATION = "/sdcard/"; //android directory picker is needed 

private URL url; 
private ArrayList<Byte> bytes = new ArrayList<>(); 

public AsyncDownload(URL url){ 
    this.url = url; 
} 

@Override 
protected Void doInBackground(Void... params){ 

    try{ 
     HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
     BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 

     ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

     int c; 
     while ((c = in.read()) != -1){ 
      buffer.write(c); 
     } 

     Log.i(TAG, buffer.toString()); 

     Random rand = new Random(4L); 
     String temp = String.valueOf(rand.nextInt()); 

     String finalLocation = STORAGE_LOCATION + temp; 

     File file = new File(finalLocation); 
     file.getParentFile().mkdirs(); 
     file.setWritable(true); 
     file.setReadable(true); 

     FileOutputStream fOut = new FileOutputStream(file); 
     fOut.write(buffer.toByteArray()); 
     fOut.flush(); 
     fOut.close(); 
     FileInputStream fIn = new FileInputStream(finalLocation); 

     String reRead = new String(); 
     int a; 
     while ((a = fIn.read()) != -1){ 
      reRead += a; 
     } 

     Log.i(TAG, reRead); 

     //this section is for automatic file naming 
     /*Random rand = new Random(5L); 
     String fileNumber = String.valueOf(rand.nextInt()); 
     StringBuilder sb = new StringBuilder(); 
     sb.append(fileNumber).append("download"); //definitely needs work 

     Log.i(TAG, sb.toString());*/ 

     //FileOutputStream fOut = new FileOutputStream() 

    }catch (IOException ioe){ 
     Log.e(TAG, "network error" + ioe.toString(), ioe); 
    } 


    return null; 
} 
} 

我很新,所以我可能已經犯了一些非常明顯的錯誤。請幫忙解決這個錯誤。謝謝。

+0

什麼API級別,你運行的?從6.0或更高版本開始,如果寫入外部存儲器,則必須要求用戶運行時才能獲得許可。如果您寫入應用程序特定存儲,則不需要它。 – Joshua

+0

如果您正在測試上面的設備或Android 6,則需要請求讀取和寫入權限 –

+0

您確定路徑正確嗎? – Henry

回答

1

這在你的活動

protected void checkPermissions() { 
      final int writeExternalPermissionCheck = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); 



    if (writeExternalPermissionCheck != PackageManager.PERMISSION_GRANTED { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
        Constant.REQUEST_CODE_ASK_PERMISSIONS); 
     } 
    } 
} 

添加到您的活動

if (ContextCompat.checkSelfPermission(context, 
      android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(InterviewListActivity.this, 
       new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_EXT_STORAGE); 
    } 
+0

這只是一些必要的事情。 – Henry

1

調用此方法並重寫此方法

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    switch (requestCode) { 
     case Constant.REQUEST_CODE_ASK_PERMISSIONS: 
      if (grantResults!=null) { 
       if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 

        //Call ur save method here or change the variable value true 
       } else { 
        Logger.toast(this, "Please enable write permission from Apps); 

       } 
      } 
      break; 
     default: 
      super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
    } 
} 

希望這有助於。

0

API級別6.0或以上版本,你需要運行許可