title: Accessing a certain downloaded .sqlite database in external storage from an android app
body: <p><em>I am trying to implement an offline map feature in an android WebView-based app:</em></p>
  
  <p>Using <code>DownloadManager</code>, <strong>I download an <em>sqlite database file</em> (of a structure like .mbtiles) from our webserver</strong>, which contains blobs of the map tile images (the "offline map") and store it in the <em>android external storage</em> through </p>
  
  <pre><code>public void downloadMap() {
      downloadManager = (DownloadManager) getActivity().getSystemService(Activity.DOWNLOAD_SERVICE);
      DownloadManager.Request r = new DownloadManager.Request(Uri.parse("http://sry.youtoknow.idontwant/map.sqlite"));
  
      r.setDestinationInExternalFilesDir(getContext(), "map", "map.sqlite");
  
      downloadManager.enqueue(r);
  }
  </code></pre>
  
  <p><strong>The Download seems to work perfectly well.</strong>
  I register a <code>BroadcastReceiver</code> to receive <code>DownloadManager.ACTION_DOWNLOAD_COMPLETE</code> and store the path to "map.sqlite" using <code>SharedPreferences</code>.</p>
  
  <p>To access the database from JavaScript for using the tile images in the <code>WebView</code>, <strong>I intercept XHRequests</strong> by checking for a custom fictive schema name <code>customhttp:</code> in the URL:</p>
  
  <pre><code>webView.setWebViewClient(new WebViewClient() {
      public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
          String url = request.getUrl().toString();
          if (!url.startsWith("customhttp:")) {
              return null;
          } else {
              SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
              SQLiteDatabase db = SQLiteDatabase.openDatabase(preferences.getString("map_uri", Environment.getExternalStorageDirectory().getPath() + "berlin.sqlite"), null, SQLiteDatabase.OPEN_READONLY);
          }
      }
  });
  </code></pre>
  
  <p><strong>My problem is that I seem to implement <code>openDatabase()</code> in a wrong way</strong> as I get the following unpleasant error with the corresponding line, but can't figure out why:</p>
  
  <pre><code>E/SQLiteLog(#####):      (14) cannot open file at line ##### of [##########]
  E/SQLiteLog(#####):      (14) os_unix.c:#####: (2) open(//file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite) - 
  E/SQLiteDatabase(#####): Failed to open database 'file:///storage/emulated/0/Android/data/idontwant.youtoknow.sry/files/map/map.sqlite'.
  E/SQLiteDatabase(#####): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
  </code></pre>
  
  <p>[...]</p>
  
  <p>The file exists, is not corrupt and its path seems to be correct. I was able to open the file using an SQLite viewing app.</p>
  
  <p><strong>Question: Why does my Code not work; how can I make it work?</strong></p>
  
  <p>I am aware that there exist at least three very similar questions with the above error message here, but they are not that specific, detailed and/or do not exactly fit my needs. I also didn't manage to solve the problem after reading this article:</p>
  
  <p><a href="http://blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/">http://blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/</a>.</p>
  
  <p>Thank you very much for your help!</p>
  
  <hr>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>I tried creating a new database using <code>SQLiteDatabase.openOrCreateDatabase()</code> in external storage in order to compare it to the original database. It was not created - instead I surprisingly confronted the same error message (could not <em>open</em> database).</p>
  
  <p>Then I tried again to open a new database, this time in RAM, using <strong><code>SQLiteDatabase.openOrCreateDatabase(":memory:", null)</code></strong> and it did not throw any error.</p>
  
  <p>Thus I begin to think that the problem is some access restriction to external storage or a mistake when addressing external storage rather than the database file itself.</p>