Не удается загрузить общие настройки из файла ТОЛЬКО на Android Oreo (API 26) - PullRequest
0 голосов
/ 03 сентября 2018

EDIT

Пожалуйста, прокрутите вниз до этой темы для обновления. Я сосредоточился на проблеме, но мне все еще нужна помощь в ее решении.



Фон
В моем приложении для Android я использую следующий код для запуска диалогового окна файла и загрузки ранее сохраненного набора общих настроек:

public void load (){

    Intent intent = new Intent()
            .setType("*/*")
            .setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select a file"), 123);

}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode==123 && resultCode==RESULT_OK) {
        Uri selectedfile = data.getData(); //The uri with the location of the file
        File file = new File(selectedfile.getPath());
        loadSharedPreferencesFromFile(file);
    }
}

@SuppressWarnings({ "unchecked" })
private boolean loadSharedPreferencesFromFile(File src) {
    SharedPreferences shared = getActivity().getSharedPreferences("mypref", getActivity().MODE_PRIVATE);
    SharedPreferences.Editor editor = shared.edit();
    //
    boolean res = false;
    ObjectInputStream input = null;
    try {
        input = new ObjectInputStream(new FileInputStream(src));
        editor.clear();
        Map<String, ?> entries = (Map<String, ?>) input.readObject();
        for (Map.Entry<String, ?> entry : entries.entrySet()) {
            Object v = entry.getValue();
            String key = entry.getKey();

            if (v instanceof Boolean)
                editor.putBoolean(key, ((Boolean) v).booleanValue());
            else if (v instanceof Float)
                editor.putFloat(key, ((Float) v).floatValue());
            else if (v instanceof Integer)
                editor.putInt(key, ((Integer) v).intValue());
            else if (v instanceof Long)
                editor.putLong(key, ((Long) v).longValue());
            else if (v instanceof String)
                editor.putString(key, ((String) v));
        }
        editor.commit();
        res = true;
        Toast toast = Toast.makeText(getActivity().getApplicationContext(), "Load successful", Toast.LENGTH_LONG);
        toast.show();
        restartActivity();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }finally {
        try {
            if (input != null) {
                input.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    return res;
}

Код работает так, как задумано в старых API (я пробовал его с Kitkat и Lollipop): открывается диалоговое окно файла, файл выбирается пользователем, и (если это файл общих настроек), настройки успешно загружается в приложение.

Проблема
Приведенный выше код не работает с Oreo (API 26)!
Диалоговое окно файла успешно запускается, но как только я выбираю ранее сохраненный файл общих настроек, диалоговое окно исчезает без загрузки настроек в приложение. Очевидно, что-то ломается по пути (возможно, в loadSharedPreferencesFromFile?), Но я не могу понять, что.

Мой вопрос
Что-то изменилось в Oreo, о котором я должен знать, в отношении кода, который я использую - например, общие настройки, ObjectInputStream или что-то в этом роде? Я взглянул на официальную документацию для Oreo и не увидел ничего уместного.

Две ноты:
1) Я do явно запрашиваю у пользователя разрешение через код для записи на внешнее хранилище, что также упоминается в манифесте
2) Если какая-то разница, то сохраненный файл настроек, который я пытаюсь загрузить, был , успешно создан тем же экземпляром приложения (то есть версией Oreo), это не какой-то внешний файл, сохраненный извне.

EDIT:
Я попытался загрузить файл, минуя диалоговое окно файла - т.е. просто передавая определенный файловый объект (путь и имя файла) в loadSharedPreferencesFromFile - и это работает . Это означает, что проблема заключается в диалоге файла. Есть идеи?

РЕДАКТИРОВАТЬ 2
Из того, что я понимаю, похоже, проблема с линиями

Uri selectedfile = data.getData(); //The uri with the location of the file
File file = new File(selectedfile.getPath());
loadSharedPreferencesFromFile(file);

как Орео (или на самом деле Зефир и выше), похоже, не нравится Uri. Я искал решения, включая этот ответ, реализующий FileProvider:
Intent.ACTION_SEND не работает на Oreo
Я не смог понять, как изменить свой код. Я знаю, что мне нужно реализовать if-statement следующим образом:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
    Uri selectedfile = data.getData(); //The uri with the location of the file
}
else {
    // code for higher versions
}


Но я не уверен, что делать дальше.

  • Я добавил тег FileProvider в AndroidManifest.xml
  • Я создал provider_paths.xml

Но когда дело доходит до замены

  Uri uri = Uri.fromFile(fileImagePath);

с

  Uri uri = FileProvider.getUriForFile(MainActivity.this, 
  BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


Я заблудился, потому что в своем собственном коде я использовал Uri selectedfile = data.getData();, как мне адаптировать эту часть к этому решению?

...