Проблемы с резервным копированием sqlite db в файл на некоторых телефонах Android. mkdirs() иногда не работает

Я написал код для резервного копирования моего sqlite db на file на моем телефоне Android (Sony Ericsson X-8 с версией 2.1.1 Android).

Я привел код ниже для справки, но прежде чем читать его, я подчеркиваю, что он отлично работает на X-8. [Любые предложения по улучшению по-прежнему приветствуются!] Когда я запускаю его на Sony Ericsson Xperia Arc с версией 4.0.4 Android, у меня возникают проблемы.

Файл не записан в папку SD card. Это очень сложно отладить, потому что, как вы, возможно, знаете, подключение телефона к компьютеру через USB-карту может остановить запись файла в любом случае (см., Например: Android FileWriter не работает на Sony Ericsson Arc, но работает на другом телефоне).

В любом случае просмотр кода в отладчике не приводит к проблемам, и создается впечатление, что файл записан. В моем manifest у меня есть:

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

Я в тупике относительно того, что происходит. Что-то изменилось между версиями 2 и 4 Android в отношении файловой системы? Это конкретно для телефона?

Любые идеи будут высоко оценены. -Дэйв

                        String packageName = "com.xxx.receiver";
                    String dbName = "Receiver";
                    //File sd = Environment.getExternalStorageDirectory();   
                    File sd = new File(Environment.getExternalStorageDirectory(), "xxx"); // "xxx" is never created on Arc!
                    if (!sd.exists()) { 
                        sd.mkdirs(); 
                    } 
                    File data = Environment.getDataDirectory();     
                    if (sd.canWrite())
                    {                    
                        String currentDBPath = "//data//"+ packageName +"//databases//"+ dbName; 
                        String backupDBPath = dbName;   
                        File currentDB = new File(data, currentDBPath); 
                        File backupDB = new File(sd, backupDBPath);    
                        FileChannel src = new FileInputStream(currentDB).getChannel();  
                        FileChannel dst = new FileOutputStream(backupDB).getChannel();   
                        dst.transferFrom(src, 0, src.size());    
                        src.close();                      
                        dst.close();                  
                        //Toast.makeText(SettingsAdapter.this.getContext(), backupDB.toString(), Toast.LENGTH_LONG).show(); 
                    }               

person Dave    schedule 28.02.2013    source источник
comment
Что возвращает sd.getAbsolutePath() перед if( !sd.exists() )?   -  person 323go    schedule 01.03.2013
comment
323go, На обоих телефонах (тот, который работает, и тот, который не работает) sd.getAbsolutePath() дает /mnt/sdcard/xxx.   -  person Dave    schedule 01.03.2013
comment
Вы пытались найти этот путь (/mnt/sdcard) в оболочке adb? Тогда попробуйте mkdir оттуда?   -  person 323go    schedule 01.03.2013
comment
323go, Xperia Arc — это странно! Попробовал ваше предложение и создал каталог yyy на обоих телефонах с оболочкой adb. Это сработало. НО, yyy не отображается на Xperia Arc в проводнике Windows. НО, теперь я вижу свой исходный каталог xxx И sqlite db, который мне нужен. Оно волшебным образом появилось. Спасибо! Это заставляет меня задаться вопросом, появится ли каталог yyy в конце концов в проводнике Windows. Спасибо за введение в оболочку adb; кажется, что это будет полезно и, возможно, более точно, чем проводник Windows. Подумайте о том, чтобы оставить комментарии в ответ, и я был бы счастлив и благодарен отметить!   -  person Dave    schedule 01.03.2013
comment
Как вы подключаетесь к устройству? MTP или Mass Storage? Если вы подключаетесь через MTP, папки (в проводнике Windows) не обновляются до тех пор, пока вы не запустите повторное сканирование носителя.   -  person 323go    schedule 01.03.2013
comment
На данный момент я почти уверен, что у вас есть проблема с файлом, который не считывается MediaScanner. Я опубликую стандартный код, который я использую, чтобы Android распознавал недавно добавленные файлы в качестве ответа (потому что код плохо форматируется в комментариях). Если это не решит вашу проблему, дайте мне знать, и я удалю ее, чтобы не смущать других читателей.   -  person 323go    schedule 01.03.2013
comment
Не могли бы вы сказать, как запустить повторное сканирование носителя в проводнике Windows в Windows XP и Windows 7. Возможно ли это из проводника. Или может через adb?   -  person Dave    schedule 02.03.2013
comment
Вы можете запустить его через adb, отправив трансляцию через диспетчер активности: ./adb shell am broadcast -a android.intent.action.MEDIA_MOUNTED ...   -  person 323go    schedule 02.03.2013


Ответы (1)


В Android, начиная с ICS, USB-подключения по умолчанию предлагают устройства в качестве мультимедийного устройства, а не USB-накопителя. Преимущество этого в том, что внешнее хранилище не «исчезает» при подключении USB-кабеля, что, конечно же, значительно упрощает отладку. Недостатком является то, что вам нужно будет явно сообщить Android, когда вы добавили файл (или файлы).

Впрочем, это не так уж и сложно:

File sd = new File(Environment.getExternalStorageDirectory(), "xxx" );
...
// create your file in xxx
... 
sendBroadcast( 
    new Intent( Intent.ACTION_MEDIA_MOUNTED, 
                Uri.fromFile( sd ) ) 
              ) 
    );

В качестве примечания вместо жесткого кодирования пути к базе данных вы можете использовать это:

context.getDatabasePath( dbName );
person 323go    schedule 01.03.2013
comment
Большое спасибо за ваш ответ и, что более важно, ваши комментарии к моему исходному сообщению. - person Dave; 01.03.2013