Issue writing in the Download directory

两盒软妹~` 提交于 2021-02-05 06:22:26

问题


I'm trying to write this xlsx file in the Download directory of a Samsung Galaxy Tab A 2019 (Android 9.0). If I try to do this on my emulator (Google Pixel C with android 9.0) it works without any problems and I can see the file. If I give the app to my client it gives an error, catches by up by this function:

try {
     importIntoExcel();
     DynamicToast.makeSuccess(UserList.this, "Saved!", 2000).show();
     b1.setEnabled(true);
} catch (IOException e) {
     DynamicToast.makeError(UserList.this, "Error!", 2000).show();
     e.printStackTrace();
}

Unfortunately I cannot see the stack trace since I cannot connect the client's tablet to my PC. This is the method which doesn't works:

private void importIntoExcel() throws IOException {
    String[] columns = {"Numero Test", "Codice ID", "Genere", "Data di nascita", "Protocollo", "Data del test", " ", "Cornice", "Nome cornice", "Fluidità", "Flessibilità",
            "Originalita'", "Elaborazione'", "Titolo", "Tempo Reazione", "Tempo Completamento", "Numero cancellature", "Numero Undo"};


    Workbook workbook = new XSSFWorkbook();
    Sheet sheet = workbook.createSheet("RiepilogoTest");

    Font headerFont = workbook.createFont();
    headerFont.setBold(true);
    headerFont.setFontHeightInPoints((short) 14);
    headerFont.setColor(IndexedColors.RED.getIndex());

    CellStyle headerCellStyle = workbook.createCellStyle();
    headerCellStyle.setFont(headerFont);
    headerCellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);

    // Create a Row
    Row headerRow = sheet.createRow(0);

    for (int i = 0; i < columns.length; i++) {
        Cell cell = headerRow.createCell(i);
        cell.setCellValue(columns[i]);
        cell.setCellStyle(headerCellStyle);

    }

    // Create Other rows and cells with contacts data
    int rowNum = 1;

    //Inserting the data
    File dir = new File("/data/user/0/com.example.williamstest/");

    for (File file : dir.listFiles()) {
        if (file.getName().startsWith("app_draw")) {
            String typeTest = file.getName().replaceAll("[^\\d.]", "");
            if (new File(file.getAbsolutePath() + "/infotest.txt").exists()) {
                FileReader f = new FileReader(file.getAbsolutePath() + "/infotest.txt");
                LineNumberReader reader = new LineNumberReader(f);
                String line;
                String protocollo = "";
                line = reader.readLine();
                Row row = null;
                if (line.equals(userLogged)) {
                    row = sheet.createRow(rowNum++);
                    row.createCell(0).setCellValue("Test: " + typeTest);
                    line = reader.readLine();
                    row.createCell(2).setCellValue(line);
                    line = reader.readLine();
                    if (line.equals("0")) row.createCell(2).setCellValue("/");
                    row.createCell(3).setCellValue(line);
                    line = reader.readLine();
                    protocollo = line;
                    row.createCell(4).setCellValue(line);
                    line = reader.readLine();
                    row.createCell(5).setCellValue(line);
                    line = reader.readLine();
                    row.createCell(1).setCellValue(line);
                }
                for (int i=0; i<12; i++) {
                    String content = "";
                    reader = new LineNumberReader(new FileReader(file.getAbsolutePath() + "/" + protocollo + (i + 1) + "_score.txt"));
                    while ((line = reader.readLine()) != null) {
                        content+=line+"\n";
                    }

                    String[] values = content.split("\n");
                    row.createCell(6).setCellValue(" "); //Vuota
                    row.createCell(7).setCellValue(i+1); //Cornice
                    row.createCell(8).setCellValue(values[4]); //Nome cornice
                    row.createCell(9).setCellValue(values[0]); //Fluidita
                    row.createCell(10).setCellValue(values[1]); //Flessibilita
                    row.createCell(11).setCellValue(values[2]); //Originalita'
                    row.createCell(12).setCellValue(values[3]); //Elaborazione
                    row.createCell(13).setCellValue(values[9]); //Titolo
                    row.createCell(14).setCellValue(values[5]); //Tempo reazione
                    row.createCell(15).setCellValue(values[6]); //Tempo Completamento
                    row.createCell(16).setCellValue(values[7]); //Numero cancellature
                    row.createCell(17).setCellValue(values[8]); //Numero undo

                    row = sheet.createRow(rowNum++);
                    row.createCell(0).setCellValue(" ");
                    row.createCell(1).setCellValue(" ");
                    row.createCell(2).setCellValue(" ");
                    row.createCell(3).setCellValue(" ");
                    row.createCell(4).setCellValue(" ");
                    row.createCell(5).setCellValue(" ");
                }
                f.close();
            }
        }
    }

    sheet.setDefaultColumnWidth(23);

    // Write the output to a file
    if (new File(Environment.getExternalStorageDirectory(), "Download/risultatiTest.xlsx").exists())
        new File(Environment.getExternalStorageDirectory(), "Download/risultatiTest.xlsx").delete();
    FileOutputStream fileOut = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "Download/risultatiTest.xlsx"));
    workbook.write(fileOut);
    fileOut.close();
}

I also wrote this method which saves in the same directory and it works, so I don't think it's a permission problem:

private void generateImages() throws IOException {
    File dir = new File("/data/user/0/com.example.williamstest/");
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "/Download/ImmaginiTest");
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs())
            Log.d("App", "failed to create directory");
    } else {
            if (mediaStorageDir.isDirectory()) {
                for (File child : mediaStorageDir.listFiles())
                    deleteRecursive(child);
            }
            mediaStorageDir.delete();
            mediaStorageDir.mkdirs();
        }
    for (File file : dir.listFiles()) {
        if (file.getName().startsWith("app_draw") && Character.isDigit(file.getName().charAt(file.getName().length() - 1))) {
            File makingDir = new File(Environment.getExternalStorageDirectory(), "/Download/ImmaginiTest/Test"+file.getName().substring(file.getName().length() - 1));
            makingDir.mkdirs();
            for (File fileS : file.listFiles()) {
                if (fileS.getName().endsWith(".png")) {
                    Bitmap b = BitmapFactory.decodeStream(new FileInputStream(fileS));
                    File mypath=new File(makingDir, fileS.getName());
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(mypath);
                        b.compress(Bitmap.CompressFormat.PNG, 100, fos);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

回答1:


On some devices and in newer Android versions Environment.getExternalStorageDirectory() no longer returns a valid path. Try using Context.getExternalFilesDir(null) instead, it should return this path: /storage/emulated/0/Android/data/your.package.name/. Try it out to see if thats the issue. Here's the doc.

I recommend you to emulate some similar Samsung devices and see if you can replicate the error to have a look at the logcat output




回答2:


Do you have any logcat that could be use to narrow down where the error comes from ?

Also you could begin by avoiding using such magic string:

  • File dir = new File("/data/user/0/com.example.williamstest/");
  • File makingDir = new File(Environment.getExternalStorageDirectory(), "/Download/ImmaginiTest/Test"+file.getName().substring(file.getName().length() - 1));

As of API 29 Environment.getExternalStoragePublicDirectory() is deprecated. Look at this AndroidStudio getExternalStoragePublicDirectory in API 29 instead.




回答3:


Traditionally, the external storage is typically an SD card but it may also be implemented as built-in storage.

Thus it is necessary to verify if you have one and if it is mounted before accessing a file in the Environment.getExternalStorageDirectory(). Otherwise, you need an internal directory as a fallback. Check out the doc here to know how to.

Also, if you are targetting API level 29, make sure you use android:requestLegacyExternalStorage="true" on your manifest's application tag too. Check it out here.




回答4:


Probably the writing files on computers and android devices are different. The new android versions are blocking applications access to some folders. So try different folder to write it in. Maybe don’t create new folder and write it in existing.

Also as others say Environment.getExternalStorageDirectory() is deprecated and you should not use it on newer android version, but older ones you still could.

Also you can’t 100% trust emulators, because it is not 100% same



来源:https://stackoverflow.com/questions/60658374/issue-writing-in-the-download-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!