2011-01-17 4 views
9

최근에 나는 HTC Desire 시리즈에 대해 많은 불만을 겪었으며 SQL 문을 호출하는 동안 오류가 발생했습니다. 다음을 포함하는 로그 스냅 샷이있는 사용자로부터 보고서를 받았습니다. Sqlite가 HTC Desire HD 문제를 일으켰습니다.

I/Database(2348): sqlite returned: error code = 8, msg = statement aborts at 1: [pragma journal_mode = WAL;] 
E/Database(2348): sqlite3_exec to set journal_mode of /data/data/my.app.package/files/localized_db_en_uk-1.sqlite to WAL failed 

호출이 커서가 열려 것으로 자체 명단 심각한 런타임 오류의 데이터베이스 결과를 열 수 있기 때문에 내 응용 프로그램은 기본적으로 화염에 불타는 하였다. 커서를 열려고 시도 할 때 커서가 없어야합니다.

이것은 HTC Desire HD 및 Z에서만 발생합니다. 기본적으로 내 코드는 다음을 수행합니다 (문제 영역을 분리하기 위해 약간 변경됨).

SQLiteDatabase db; 
String dbName; 

public SQLiteDatabase loadDb(Context context) throws IOException{ 
    //Close any old db handle 
    if (db != null && db.isOpen()) { 
     db.close(); 
    } 
    // The name of the database to use from the bundled assets. 
    String dbAsset = "/asset_dir/"+dbName+".sqlite"; 
    InputStream myInput = context.getAssets().open(dbAsset, Context.MODE_PRIVATE); 

    // Create a file in the app's file directory since sqlite requires a path 
    // Not ideal but we will copy the file out of our bundled assets and open it 
    // it in another location. 
    FileOutputStream myOutput = context.openFileOutput(dbName, Context.MODE_PRIVATE); 

    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = myInput.read(buffer)) > 0) { 
     myOutput.write(buffer, 0, length); 
    } 

    // Close the streams 
    myOutput.flush(); 
    // Guarantee Write! 
    myOutput.getFD().sync(); 
    myOutput.close(); 
    myInput.close(); 
    // Not grab the newly written file 
    File fileObj = context.getFileStreamPath(dbName); 
    // and open the database 
    return db = SQLiteDatabase.openDatabase(fileObj.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
} 

슬프게도이 휴대 전화는 영국에서만 사용 가능하며 인벤토리에없는 휴대 전화입니다. HTC Desire 시리즈에서만이 유형의 보고서를 받고 있습니다. 이 코드가 아무런 문제없이 작동하면서 변경된 사항을 알 수 없습니다. 제가 누락 된 것이 있습니까?

답변

20

짧은 대답 : SQLiteDatabase.OPEN_READONLY을 삭제 해보세요.

긴 대답 :

은 "WAL"는 미리 쓰기 로그, SQLite는 비교적 새로운 기능 내가 그것을 이해합니다. WAL의 SQLite 문서는 "읽기 전용 WAL 데이터베이스를 열 수 없습니다."라고 말합니다. 이제는 읽기 전용 미디어와 관련하여 더 많은 것으로 보입니다. 그러나 OPEN_READONLY에 대해서는 사실 일 수 있습니다.

는 것을 가정으로 나는이 도움이된다면 다소 놀라실 겁니다 :

  • WAL 그 두 장치에 환경에 대한 특별한
  • 뭔가 WAL을 활성화 표준 안드로이드
  • HTC에서 사용되지 않습니다 (예를 들어, 자산에서 탈락하고있는 바이너리 데이터베이스) 일반적인 읽기 전용 데이터베이스가 정상적으로 작동하는 곳에서 이러한 문제가 발생합니다. 이러한 장치가 깨진 읽기 전용 데이터베이스 지원을 통해 호환성 테스트를 통과했다고 상상할 수 없습니다.

하지만 적어도 가치가 있다고 생각합니다.

또한 데이터베이스를 빌드/채우고 실행하기 위해 SQL 문을 패키징하기 위해 바이너리 데이터베이스 패키지를 전환하는 것을 고려할 수 있습니다. 트랜잭션 속도가 느려지지만 트랜잭션을 사용하지 않으면 속도가 느려지므로 데이터베이스 파일 관련 문제가 발생할 가능성이 적습니다.

+0

나는 그것이 가치가있는 것처럼 들린다, 나는 내일 이것을 명확히 시험 할 것이다. 작동하면 체크 박스와 맥주가 생깁니다. –

+0

기니아 피그를 찾아 냈습니다. 감사! 그것은 동시에 굉장하고 슬 was습니다. –

+1

@ 그렉 : "it worked"... 'SQLiteDatabase.OPEN_READONLY'을 (를) 제거하고 있습니까? 앞으로 호환성 문제를 막을 수 있도록 호환성 테스트 스위트의 차이점을 알려 주시기 바랍니다. 감사! – CommonsWare

0

기본적으로 근본적인 문제는 sqlite3 데이터베이스 파일이 Android 장치간에 이식 가능한 것으로 가정한다는 것입니다. 이것은 사실이 아닙니다. 파일 형식 (실제로 SQLite를 데이터베이스 엔진으로 사용하는 경우)은 이 아니며 API의 일부분은입니다. HTC는 sqlite3 대신 postgres를 사용하는 Android 휴대 전화를 만들 수 있으며 공식적으로 호환 될 수 있습니다.

예, 응용 프로그램의 자산에 sqlite3 .db 파일을 번들링 한 다음 설치 후 그대로 사용하여 데이터베이스 콘텐츠를 미리 채우는 것이 일반적입니다. 하지만 Android 플랫폼의 동일한 버전을 실행하는 기기 간에는 작동하지 않을 수도 있습니다. 당신이 확신 할 수있는 유일한 것은 바로 그것입니다.주어진 버전의 Android를 실행하는 특정 장치에서 생성 된 db 파일은 같은 실제 장치에서 계속 사용할 수 있으며 동일한 시스템 공급 업체의 동일한 또는 이후 Android 빌드를 실행합니다.

(동일한 공급 업체의 동일한 모델의 장치조차도 아닙니까? 아니오 : 두 장치가 같은 방식으로 브랜드화되어 실제로 동일한 시스템 빌드를 실행하지 않을 수도 있고 다른 지점에서 동일한 하드웨어를 사용해야 할 수도 있습니다.)

이 이동식 작업을 수행하는 유일한 방법은 원시 데이터베이스 파일 자체를 포함시키지 않고 공개 API에 재생하여 장치에 적합한 데이터베이스 파일을 설정하는 일반화 된 구문 분석 표현을 삽입하는 것입니다.

+2

파일 형식이 변경 될 수 있으므로 한 컴퓨터에서 다른 컴퓨터로 파일을 전송하지 마십시오. 그게 좋은 대답이나 진실한 생각이라고 생각하지 않습니다. 이 가정을 뒷받침 할 증거가 있습니까? 문제는 SDK가 sqlite, sqlite 3.4.0을 정확히 호출하는 것 같습니다 : http://developer.android.com/reference/android/database/sqlite/package-summary.html이 공급 업체는 실제로 따르지 않았습니다. 이. 또한 필요가있는 잠금이나 저널링이 없으므로 ReadOnly 데이터베이스에는 WAL이 필요하지 않습니다. –

+0

클래스 및 메서드의 이름을 읽고 해당 클래스 및 메서드의 _implementation_에 대한 계약을 구성한다고 가정합니다. 불행히도 실제로는 그렇지 않습니다. 이 냄새가 나는데 동의합니다. 근본적인 문제를 제정신이고 이식성있는 방식으로 해결하고 싶습니다. 하지만 그것은 그런 문제에 부딪치지 않는 사람들을 돕지 않을 것입니다. – ctate

+0

나 자신의 뷰 클래스도 구현해야합니까? 공급 업체가 수명주기를 임의로 대체합니까? 죄송합니다. API의 어떤 부분을 신뢰할 수 있어야하는지 혼란 스럽습니다. 그 이후로 문제를 고쳤지만 귀하의 의견은 내가 설명서를 읽고 그들이 문서화 된대로 행동 할 것으로 기대했기 때문에 그런 것들이 단지 기대되는 것만 믿을 수 없어 충격적이지 않습니다. –

관련 문제