OpenHelper.java revision 04c1c2afb7481e7fb9b66f96023c79d19cad8c90
1c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey/* 2c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project 3c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * 4c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * you may not use this file except in compliance with the License. 6c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * You may obtain a copy of the License at 7c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * 8c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * 10c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * See the License for the specific language governing permissions and 14c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey * limitations under the License. 15c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey */ 16c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 17c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeypackage com.android.providers.downloads; 18c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 19169ab531ca6bb2f43ed18fe2b03f66c808f12b81Jeff Sharkeyimport static android.app.DownloadManager.COLUMN_LOCAL_FILENAME; 20c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport static android.app.DownloadManager.COLUMN_LOCAL_URI; 21c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport static android.app.DownloadManager.COLUMN_MEDIA_TYPE; 22c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport static android.app.DownloadManager.COLUMN_URI; 23c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport static android.provider.Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI; 248ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkeyimport static com.android.providers.downloads.Constants.TAG; 25c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 26c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.app.DownloadManager; 278ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkeyimport android.content.ActivityNotFoundException; 28c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.content.ContentUris; 29c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.content.Context; 30c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.content.Intent; 31c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.database.Cursor; 32c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.net.Uri; 33c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeyimport android.provider.Downloads.Impl.RequestHeaders; 348ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkeyimport android.util.Log; 35c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 365cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkeyimport java.io.File; 375cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey 38c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkeypublic class OpenHelper { 39c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey /** 408ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey * Build and start an {@link Intent} to view the download with given ID, 418ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey * handling subtleties around installing packages. 42c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey */ 438ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey public static boolean startViewIntent(Context context, long id, int intentFlags) { 448ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey final Intent intent = OpenHelper.buildViewIntent(context, id); 458ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey if (intent == null) { 468ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey Log.w(TAG, "No intent built for " + id); 478ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey return false; 488ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey } 498ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey 508ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey intent.addFlags(intentFlags); 518ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey try { 528ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey context.startActivity(intent); 538ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey return true; 548ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey } catch (ActivityNotFoundException e) { 558ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey Log.w(TAG, "Failed to start " + intent + ": " + e); 568ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey return false; 578ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey } 588ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey } 598ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey 608ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey /** 618ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey * Build an {@link Intent} to view the download with given ID, handling 628ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey * subtleties around installing packages. 638ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey */ 648ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey private static Intent buildViewIntent(Context context, long id) { 65c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final DownloadManager downManager = (DownloadManager) context.getSystemService( 66c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey Context.DOWNLOAD_SERVICE); 67c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey downManager.setAccessAllDownloads(true); 68c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 69c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Cursor cursor = downManager.query(new DownloadManager.Query().setFilterById(id)); 70c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey try { 71c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey if (!cursor.moveToFirst()) { 728ec87ea5a5c191554d6205d4c779768664b1724bJeff Sharkey return null; 73c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 74c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 75c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Uri localUri = getCursorUri(cursor, COLUMN_LOCAL_URI); 765cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey final File file = getCursorFile(cursor, COLUMN_LOCAL_FILENAME); 77169ab531ca6bb2f43ed18fe2b03f66c808f12b81Jeff Sharkey String mimeType = getCursorString(cursor, COLUMN_MEDIA_TYPE); 785cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey mimeType = DownloadDrmHelper.getOriginalMimeType(context, file, mimeType); 79c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 80c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Intent intent = new Intent(Intent.ACTION_VIEW); 81c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 82c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey if ("application/vnd.android.package-archive".equals(mimeType)) { 83c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey // PackageInstaller doesn't like content URIs, so open file 84c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey intent.setDataAndType(localUri, mimeType); 85c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 86c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey // Also splice in details about where it came from 87c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Uri remoteUri = getCursorUri(cursor, COLUMN_URI); 88c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey intent.putExtra(Intent.EXTRA_ORIGINATING_URI, remoteUri); 89c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey intent.putExtra(Intent.EXTRA_REFERRER, getRefererUri(context, id)); 9046bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver intent.putExtra(Intent.EXTRA_ORIGINATING_UID, getOriginatingUid(context, id)); 91c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } else if ("file".equals(localUri.getScheme())) { 9204c1c2afb7481e7fb9b66f96023c79d19cad8c90Jeff Sharkey intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 9304c1c2afb7481e7fb9b66f96023c79d19cad8c90Jeff Sharkey | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 94c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey intent.setDataAndType( 95c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey ContentUris.withAppendedId(ALL_DOWNLOADS_CONTENT_URI, id), mimeType); 96c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } else { 9704c1c2afb7481e7fb9b66f96023c79d19cad8c90Jeff Sharkey intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 98c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey intent.setDataAndType(localUri, mimeType); 99c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 100c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 101c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey return intent; 102c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } finally { 103c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey cursor.close(); 104c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 105c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 106c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 107c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey private static Uri getRefererUri(Context context, long id) { 108c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Uri headersUri = Uri.withAppendedPath( 109c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey ContentUris.withAppendedId(ALL_DOWNLOADS_CONTENT_URI, id), 110c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey RequestHeaders.URI_SEGMENT); 111c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final Cursor headers = context.getContentResolver() 112c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey .query(headersUri, null, null, null, null); 113c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey try { 114c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey while (headers.moveToNext()) { 115c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey final String header = getCursorString(headers, RequestHeaders.COLUMN_HEADER); 116c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey if ("Referer".equalsIgnoreCase(header)) { 117c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey return getCursorUri(headers, RequestHeaders.COLUMN_VALUE); 118c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 119c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 120c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } finally { 121c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey headers.close(); 122c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 123c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey return null; 124c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 125c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 12646bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver private static int getOriginatingUid(Context context, long id) { 12746bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver final Uri uri = ContentUris.withAppendedId(ALL_DOWNLOADS_CONTENT_URI, id); 12846bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver final Cursor cursor = context.getContentResolver().query(uri, new String[]{Constants.UID}, 12946bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver null, null, null); 13046bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver if (cursor != null) { 13146bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver try { 13246bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver if (cursor.moveToFirst()) { 13346bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver return cursor.getInt(cursor.getColumnIndexOrThrow(Constants.UID)); 13446bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver } 13546bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver } finally { 13646bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver cursor.close(); 13746bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver } 13846bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver } 13946bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver return -1; 14046bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver } 14146bb7dd18c9b092d352d76ab44a4e52951941b2cBen Gruver 142c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey private static String getCursorString(Cursor cursor, String column) { 143c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey return cursor.getString(cursor.getColumnIndexOrThrow(column)); 144c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 145c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 146c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey private static Uri getCursorUri(Cursor cursor, String column) { 147c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey return Uri.parse(getCursorString(cursor, column)); 148c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey } 149c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey 1505cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey private static File getCursorFile(Cursor cursor, String column) { 1515cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey return new File(cursor.getString(cursor.getColumnIndexOrThrow(column))); 1525cff4ecb10e89e4fb39cd9e39b8753a31efbe3ccJeff Sharkey } 153c0622bf896c1af62b0e69b18cd84c7de3b67beb3Jeff Sharkey} 154