1ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong/* 2ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Copyright (C) 2013 The Android Open Source Project 3ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * 4ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 5ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * you may not use this file except in compliance with the License. 6ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * You may obtain a copy of the License at 7ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * 8ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * http://www.apache.org/licenses/LICENSE-2.0 9ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * 10ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Unless required by applicable law or agreed to in writing, software 11ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * distributed under the License is distributed on an "AS IS" BASIS, 12ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * See the License for the specific language governing permissions and 14ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * limitations under the License. 15ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong */ 16ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 17ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongpackage com.android.camera; 18ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 19ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.app.Service; 20ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.content.ContentResolver; 2183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.content.ContentValues; 22ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.content.Intent; 236df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liuimport android.graphics.BitmapFactory; 24ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.location.Location; 25ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.net.Uri; 26ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.os.AsyncTask; 27ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.os.Binder; 28ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.os.IBinder; 2983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.provider.MediaStore.Video; 30ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.util.Log; 31ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 32a16e7b50f3148f581439509279f242092e254309ztenghuiimport com.android.camera.exif.ExifInterface; 330d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong 3483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport java.io.File; 3583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 3686d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong/* 3786d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong * Service for saving images in the background thread. 3886d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong */ 39ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongpublic class MediaSaveService extends Service { 403973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu public static final String VIDEO_BASE_URI = "content://media/external/video/media"; 413973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu 42c40c411683da5db1e393e2172a451c3f9c511811Angus Kong // The memory limit for unsaved image is 20MB. 43c40c411683da5db1e393e2172a451c3f9c511811Angus Kong private static final int SAVE_TASK_MEMORY_LIMIT = 20 * 1024 * 1024; 44c40c411683da5db1e393e2172a451c3f9c511811Angus Kong private static final String TAG = "CAM_" + MediaSaveService.class.getSimpleName(); 45ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 46ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private final IBinder mBinder = new LocalBinder(); 47ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private Listener mListener; 48c40c411683da5db1e393e2172a451c3f9c511811Angus Kong // Memory used by the total queued save request, in bytes. 49c40c411683da5db1e393e2172a451c3f9c511811Angus Kong private long mMemoryUse; 50ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 51a9d66bdab247626b31dc182c4d62520b3abffdbdRuben Brunk public interface Listener { 52d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onQueueStatus(boolean full); 53ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 54ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 55a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling public interface OnMediaSavedListener { 56ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public void onMediaSaved(Uri uri); 57ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 58ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 59ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong class LocalBinder extends Binder { 60ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public MediaSaveService getService() { 61ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return MediaSaveService.this; 62ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 63ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 64ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 65ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 66ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public IBinder onBind(Intent intent) { 67ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return mBinder; 68ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 69ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 70ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 71ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public int onStartCommand(Intent intent, int flag, int startId) { 72ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return START_STICKY; 73ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 74ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 75ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 76ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public void onDestroy() { 77ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 78ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 79ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 80ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public void onCreate() { 81c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse = 0; 82ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 83ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 84ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public boolean isQueueFull() { 85c40c411683da5db1e393e2172a451c3f9c511811Angus Kong return (mMemoryUse >= SAVE_TASK_MEMORY_LIMIT); 86ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 87ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 88ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public void addImage(final byte[] data, String title, long date, Location loc, 890d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong int width, int height, int orientation, ExifInterface exif, 90ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong OnMediaSavedListener l, ContentResolver resolver) { 91ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong if (isQueueFull()) { 92ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong Log.e(TAG, "Cannot add image when the queue is full"); 93ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return; 94ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 9583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong ImageSaveTask t = new ImageSaveTask(data, title, date, 9683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong (loc == null) ? null : new Location(loc), 970d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong width, height, orientation, exif, resolver, l); 98ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 99c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse += data.length; 100ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong if (isQueueFull()) { 101ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong onQueueFull(); 102ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 103ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong t.execute(); 104ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 105ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 1066df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu public void addImage(final byte[] data, String title, long date, Location loc, 1076df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu int orientation, ExifInterface exif, 1086df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu OnMediaSavedListener l, ContentResolver resolver) { 1096df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // When dimensions are unknown, pass 0 as width and height, 1106df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // and decode image for width and height later in a background thread 1116df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu addImage(data, title, date, loc, 0, 0, orientation, exif, l, resolver); 1126df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu } 113c40c411683da5db1e393e2172a451c3f9c511811Angus Kong public void addImage(final byte[] data, String title, Location loc, 114c40c411683da5db1e393e2172a451c3f9c511811Angus Kong int width, int height, int orientation, ExifInterface exif, 115c40c411683da5db1e393e2172a451c3f9c511811Angus Kong OnMediaSavedListener l, ContentResolver resolver) { 116c40c411683da5db1e393e2172a451c3f9c511811Angus Kong addImage(data, title, System.currentTimeMillis(), loc, width, height, 117c40c411683da5db1e393e2172a451c3f9c511811Angus Kong orientation, exif, l, resolver); 118c40c411683da5db1e393e2172a451c3f9c511811Angus Kong } 119c40c411683da5db1e393e2172a451c3f9c511811Angus Kong 12083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong public void addVideo(String path, long duration, ContentValues values, 12183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong OnMediaSavedListener l, ContentResolver resolver) { 12283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // We don't set a queue limit for video saving because the file 12383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // is already in the storage. Only updating the database. 12483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong new VideoSaveTask(path, duration, values, l, resolver).execute(); 12583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 12683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 127ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public void setListener(Listener l) { 128ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong mListener = l; 129ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong if (l == null) return; 130d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb l.onQueueStatus(isQueueFull()); 131ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 132ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 133ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private void onQueueFull() { 134d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mListener != null) mListener.onQueueStatus(true); 135ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 136ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 137ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private void onQueueAvailable() { 138d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mListener != null) mListener.onQueueStatus(false); 139ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 140ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 14183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private class ImageSaveTask extends AsyncTask <Void, Void, Uri> { 142ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private byte[] data; 143ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private String title; 144ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private long date; 145ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private Location loc; 146ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private int width, height; 147ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private int orientation; 1480d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong private ExifInterface exif; 149ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private ContentResolver resolver; 150ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private OnMediaSavedListener listener; 151ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 15283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong public ImageSaveTask(byte[] data, String title, long date, Location loc, 15383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong int width, int height, int orientation, ExifInterface exif, 15483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong ContentResolver resolver, OnMediaSavedListener listener) { 155ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.data = data; 156ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.title = title; 157ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.date = date; 158ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.loc = loc; 159ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.width = width; 160ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.height = height; 161ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.orientation = orientation; 1620d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong this.exif = exif; 163ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.resolver = resolver; 164ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.listener = listener; 165ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 166ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 167ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 168ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected void onPreExecute() { 169ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong // do nothing. 170ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 171ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 172ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 173ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected Uri doInBackground(Void... v) { 1746df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu if (width == 0 || height == 0) { 1756df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // Decode bounds 1766df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu BitmapFactory.Options options = new BitmapFactory.Options(); 1776df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu options.inJustDecodeBounds = true; 1786df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu BitmapFactory.decodeByteArray(data, 0, data.length, options); 1796df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu width = options.outWidth; 1806df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu height = options.outHeight; 1816df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu } 182ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return Storage.addImage( 1830d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong resolver, title, date, loc, orientation, exif, data, width, height); 184ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 185ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 186ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 187ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected void onPostExecute(Uri uri) { 18883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong if (listener != null) listener.onMediaSaved(uri); 189c40c411683da5db1e393e2172a451c3f9c511811Angus Kong boolean previouslyFull = isQueueFull(); 190c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse -= data.length; 191c40c411683da5db1e393e2172a451c3f9c511811Angus Kong if (isQueueFull() != previouslyFull) onQueueAvailable(); 192ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 193ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 19483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 19583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private class VideoSaveTask extends AsyncTask <Void, Void, Uri> { 19683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private String path; 19783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private long duration; 19883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private ContentValues values; 19983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private OnMediaSavedListener listener; 20083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private ContentResolver resolver; 20183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 20283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong public VideoSaveTask(String path, long duration, ContentValues values, 20383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong OnMediaSavedListener l, ContentResolver r) { 20483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.path = path; 20583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.duration = duration; 20683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.values = new ContentValues(values); 20783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.listener = l; 20883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.resolver = r; 20983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 21083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 21183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong @Override 21283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong protected Uri doInBackground(Void... v) { 21383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong values.put(Video.Media.SIZE, new File(path).length()); 21483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong values.put(Video.Media.DURATION, duration); 21583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Uri uri = null; 21683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong try { 2173973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu Uri videoTable = Uri.parse(VIDEO_BASE_URI); 21883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong uri = resolver.insert(videoTable, values); 21983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 22083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // Rename the video file to the final name. This avoids other 22183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // apps reading incomplete data. We need to do it after we are 22283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // certain that the previous insert to MediaProvider is completed. 22383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong String finalName = values.getAsString( 22483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Video.Media.DATA); 22583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong if (new File(path).renameTo(new File(finalName))) { 22683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong path = finalName; 22783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 22883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 22983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong resolver.update(uri, values, null, null); 23083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } catch (Exception e) { 23183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // We failed to insert into the database. This can happen if 23283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // the SD card is unmounted. 23383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Log.e(TAG, "failed to add video to media store", e); 23483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong uri = null; 23583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } finally { 23683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Log.v(TAG, "Current video URI: " + uri); 23783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 23883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong return uri; 23983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 24083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 24183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong @Override 24283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong protected void onPostExecute(Uri uri) { 24383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong if (listener != null) listener.onMediaSaved(uri); 24483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 24583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 246ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong} 247