2015-01-15 13 views
8

Câu hỏi này đã được đăng trước đó, nhưng không có câu trả lời rõ ràng hoặc được chấp nhận và tất cả các giải pháp được cung cấp phải "hoạt động" không cho tôi. Xem tại đây: Gmail 5.0 app fails with "Permission denied for the attachment" when it receives ACTION_SEND intent"Quyền bị từ chối đối với tệp đính kèm" (trên Gmail 5.0) cố gắng đính kèm tệp vào mục đích email

Tôi có ứng dụng tích hợp dữ liệu trong tệp văn bản và cần gửi tệp văn bản cùng trong email, tự động đính kèm tệp đó. Tôi đã thử nhiều cách để có được điều này để đính kèm, và nó dường như làm việc cho Gmail 4.9 và dưới đây nhưng 5.0 có một số tính năng mới cho phép vô hiệu hóa nó làm những gì tôi muốn.

Intent i = new Intent(Intent.ACTION_SEND); 

    String to = emailRecipient.getText().toString(); 

    i.setType("message/rfc822"); 
    i.putExtra(Intent.EXTRA_EMAIL, new String[] { to }); 
    i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data"); 
    i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app."); 
    String[] dataPieces = fileManager.getListOfData(getApplicationContext()); 
    for(int i2 = 0; i2 < dataPieces.length; i2++){ 
     i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2]))); 
    } 
    i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())))); 
    Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())); 
    try { 
     startActivity(Intent.createChooser(i, "Send Email")); 
    } catch (android.content.ActivityNotFoundException ex) { 
     Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show(); 
    } 

Datapieces có thể trống nhưng dòng tệp hiện tại bên dưới vòng lặp luôn đáng tin cậy và luôn đính kèm.

Tôi đã cố gắng thay đổi

Uri.fromFile() 

để

Uri.parse() 

Khi tôi làm điều đó, nó gắn, nhưng Gmail sau đó bị treo và khi tôi kiểm tra logcat đó là vì một con trỏ null. Điều này rất có thể do Gmail không có quyền truy cập vào tệp và do đó kết quả là không có.

Tôi cũng đã cố gắng sử dụng

getCacheDir() 

thay vì

getFilesDir() 

và nó có kết quả tương tự.

Tôi đang làm gì sai ở đây và làm cách nào để tôi khắc phục sự cố? Một số ví dụ mã sẽ là thực sự, thực sự tiện dụng vì tôi mới phát triển Android và giải thích những gì tôi cần làm mà không có một số loại đẩy có lẽ sẽ không kết thúc giúp đỡ.

Cảm ơn rất nhiều.

Trả lời

6

Các bạn ổn. Hãy nghỉ ngơi và quay lại, tìm ra.

Sau đây là cách nó hoạt động, bạn cần phải có quyền ghi/đọc để lưu trữ bên ngoài, vì vậy thêm các điều khoản để biểu hiện của bạn:

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

Sau đó, tập tin của bạn đã được sao chép từ thư mục lưu trữ nội bộ của ứng dụng của bạn vào thư mục bên ngoài của ứng dụng. Tôi khuyên bạn nên sử dụng bộ nhớ trong và đó là những gì tôi đang làm ở đây để bạn có thể tự mình tìm ra thẻ SD.

Đây là khối mã thực hiện phép thuật. Nhật ký được bao gồm nhưng bạn có thể xóa chúng bằng mọi cách.

public void writeToExternal(Context context, String filename){ 
    try { 
     File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source 
     InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal 
     OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to 
     byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer 
     Log.i("Available ", is.available() + ""); 
     int result = is.read(toWrite); //Read the data from the byte array 
     Log.i("Result", result + ""); 
     os.write(toWrite); //Write it to the output stream 
     is.close(); //Close it 
     os.close(); //Close it 
     Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename); 
     Log.i("Copying from", context.getFilesDir() + File.separator + filename + ""); 
    } catch (Exception e) { 
     Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there's an error, make a piece of toast and serve it up 
    } 
} 
+4

Có sự khác biệt lớn giữa câu hỏi và giải pháp - câu hỏi là chia sẻ tệp riêng tư của ứng dụng (từ context.getFiles()) và trong câu trả lời nó trở thành từ bộ nhớ chung (~ context.getExternalFilesDir()) ... Không giống nhau ... – Felix

+0

Có giải pháp chung tốt cho các thiết bị có thể không có bộ lưu trữ gắn ngoài không? Hay liệu kịch bản đó có phải là một mối lo ngại bây giờ không? – dylansturg

+0

Sử dụng bộ nhớ ngoài để lưu trữ tệp đính kèm đã trở thành thực tiễn không tốt kể từ Android API 23 và hệ thống quyền mới của nó. Nếu bạn không yêu cầu người dùng cho phép WRITE_EXTERNAL_STORAGE khi chạy, thì nó sẽ thất bại. –

1

Đã xảy ra cùng một tệp đính kèm bị từ chối. Quyền trong tệp kê khai không có bất kỳ hiệu ứng nào, thay vì không có tác dụng nữa kể từ API 23. Cuối cùng, hãy giải quyết nó như sau.

1st cần phải kiểm tra và cấp quyền trên thời gian chạy, tôi đã làm nó trong hoạt động chính của tôi:

public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001; 
private void checkPermission(){ 
    if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
     // Should we show an explanation? 
     if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { 
      // Show an explanation to the user asynchronously 
     } else { 
      // No explanation needed, we can request the permission. 
      this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        MY_PERMISSIONS_REQUEST_READ_STORAGE); 
     } 
    } 
} 

Bây giờ khi gửi, tạo ra một tập tin trong thư mục CÔNG (cố gắng tiết kiệm vào thư mục ứng dụng của tôi - cùng vấn đề từ chối)

public File createFile(){ 
String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>"; 
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html"); 
try { 
     FileWriter writer = new FileWriter(file ,false); 
     writer.write(htmlStr); 
     } 
     writer.flush(); 
     writer.close(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    return null; 
    } 
return file; 
} 

Bây giờ soạn gửi ý định và putExtra với uri đến tập tin của bạn mà là ở lưu trữ công cộng mà người sử dụng phải cấp quyền truy cập đến và không gây vấn đề bây giờ

public void send(){ 
Intent intentSend = new Intent(android.content.Intent.ACTION_SEND); 
intentSend.setType("text/html"); 
File file = createFile(); 
if(file!=null){ 
    intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); 
} 
startActivity(Intent.createChooser(intentSend, "Send using:")); 
} 
Các vấn đề liên quan