Closed xintrea closed 4 years ago
Спасибо за помощь! Во второй раз пароль не запрашивался, т.к. по-умолчанию он запоминается после первого ввода (в настройках опция). По поводу логов - блин, в упор не вижу реальную причину краша. Куча Exception из-за попыток преобразования пустой строки в дату (в try-catch->printStackTrace()), но в конце "Хранилище загружено" (сейчас убрал printStackTrace(), чтобы не засоряло лог). Чтобы убедиться, что хранилище все-таки расшифровывается до сегфолта, можно в настройках установить опцию Запрос пароля = При старте приложения, поставить точку останова на функции onPostExecute() в классе ReadStorageTask (в файле MainActivity.java) и перезапуститься. Если остановится, значит дело в другом. Возможно, в отображении веток (в контроле MultiLevelListView).
Значит, пока не поставил настройку Запрос пароля=При старте приложения, происходит следующее.
Ставлю точку останова на первой строке метода onPostExecute() класса ReadStorageTask. При запуске, до отрисовки дерева, происходит останов на этой строке. Нажимаю продолжить выполнение, отрисовывается дерево, программа начинает работать. Если нажать на зашифрованную ветку, будет сегфолт. То есть, метод onPostExecute() больше не вызывается.
Если выстваить настройку Запрос пароля=При старте приложения то происходит следующее.
Ставлю точку останова на первой строке метода onPostExecute() класса ReadStorageTask. При запуске, до отрисовки дерева, происходит останов на этой строке. Прощелкиваю по StepOver все строки этого метода, сегфолта нет. После последней строки данного метода, где-то в более "верхнем" коде происходит сегфолт.
Да, если на последней строке этого метода нажать StepOut, чтобы "выпрыгнуть" в вызывающий код, то увидеть где был вызов невозможно, так как происходит сегфолт.
Если потыкаться по стеку вызовов, то последняя функция, в которой ошибка, вот эта:
/*** * Преобразование строки в дату * @param dateString * @return */ public static Date toDate(String dateString, String pattern) { SimpleDateFormat dateFormat = new SimpleDateFormat(pattern); Date convertedDate = null; try { convertedDate = dateFormat.parse(dateString); // <--------- Тут ошибка } catch (ParseException e) { e.printStackTrace(); } return convertedDate;
Она вызывается из такого кода (XmlManager):
private TetroidRecord readRecord(XmlPullParser parser) throws XmlPullParserException, IOException { boolean crypt = false; String id = null; String name = null; String tags = null; String author = null; String url = null; Date created = null; String dirName = null; String fileName = null; parser.require(XmlPullParser.START_TAG, ns, "record"); String tagName = parser.getName(); if (tagName.equals("record")) { crypt = ("1".equals(parser.getAttributeValue(ns, "crypt"))); id = parser.getAttributeValue(ns, "id"); name = parser.getAttributeValue(ns, "name"); tags = parser.getAttributeValue(ns, "tags"); author = parser.getAttributeValue(ns, "author"); url = parser.getAttributeValue(ns, "url"); // строка вида "yyyyMMddHHmmss" (например, "20180901211132") created = Utils.toDate(parser.getAttributeValue(ns, "ctime"), "yyyyMMddHHmmss"); // <---- Тут ошибка dirName = parser.getAttributeValue(ns, "dir"); fileName = parser.getAttributeValue(ns, "file"); }
Он в свою очередь вызывается из кода:
private List<TetroidRecord> readRecords(XmlPullParser parser) throws XmlPullParserException, IOException { List<TetroidRecord> records = new ArrayList<>(); parser.require(XmlPullParser.START_TAG, ns, "recordtable"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String tagName = parser.getName(); if (tagName.equals("record")) { TetroidRecord record = readRecord(parser); // <------- Тут ошибка records.add(record); } else { skip(parser); } } return records; }
Ну и так далее. Может, это поможет.
Я уж думал, что у меня в зашифрованных данных есть записи, в которых не указан ctime. Но таких записей нет. Команда:
cat mytetra.xml | grep "record id" | grep -v ctime
не показывает ни одной строки.
Думаю, все таки дело не в дате записи. Можете попробовать вместо строки:
created = Utils.toDate(parser.getAttributeValue(ns, "ctime"), "yyyyMMddHHmmss");
написать:
created = new Date();
Сегфолт останется.
Думаю, проблема в отображении дерева веток (при этом проблемный контрол по какой-то причине не вызывает ошибку, а молча вешает приложение). Варианты:
1) В зашифрованной ветке большое количество подветок (в т.ч. в глубину). Случается нехватка памяти, например.
2) Проблема с отображением svg-иконок. Тут можно в классе TetroidNode "заглушить" метод:
public void loadIcon(String fullFileName) {
return;
}
3) Попробовать поочередно комментировать "лишнее" в методе getViewForObject() в классе NodesListAdapter, чтобы облегчить отображение веток в дереве.
В общем, собрал проект eb0c63a2 на Android Studio.
Запустил (Run) на реальном устройстве. Программа запустилась. При попытке входа в шифрованную ветку программа запрашивает пароль. После ввода пароля программа сегфолтнулась.
Тогда запустил дебаг на реальном устройстве, чтобы получить выхлоп. Программа запустилась. При клике на зашифрованную ветку произошел сегфолт. То есть, даже пароль не успел ввести.
Выхлоп следующий: