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.content.ContentResolver; 2083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.content.ContentValues; 216df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liuimport android.graphics.BitmapFactory; 22ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.location.Location; 23ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.net.Uri; 24ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.os.AsyncTask; 2583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.provider.MediaStore.Video; 26ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 27fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kongimport com.android.camera.app.MediaSaver; 288ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItemData; 295596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 30a16e7b50f3148f581439509279f242092e254309ztenghuiimport com.android.camera.exif.ExifInterface; 310d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong 3283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport java.io.File; 33734122e8fe6c621a8510043839f05a0adff4c3a4zafirimport java.io.IOException; 3483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 35fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong/** 36fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong * A class implementing {@link com.android.camera.app.MediaSaver}. 3786d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong */ 38280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberlingpublic class MediaSaverImpl implements MediaSaver { 395596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("MediaSaverImpl"); 40280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private static final String VIDEO_BASE_URI = "content://media/external/video/media"; 413973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu 425777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar /** The memory limit for unsaved image is 30MB. */ 435777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar // TODO: Revert this back to 20 MB when CaptureSession API supports saving 445777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar // bursts. 455777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar private static final int SAVE_TASK_MEMORY_LIMIT = 30 * 1024 * 1024; 46ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 47b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling private final ContentResolver mContentResolver; 48ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 49280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling /** Memory used by the total queued save request, in bytes. */ 50280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private long mMemoryUse; 51ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 52b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling private QueueListener mQueueListener; 53b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 54b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling /** 55b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling * @param contentResolver The {@link android.content.ContentResolver} to be 56b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling * updated. 57b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling */ 58b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public MediaSaverImpl(ContentResolver contentResolver) { 59b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling mContentResolver = contentResolver; 60c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse = 0; 61ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 62ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 63fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 64ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong public boolean isQueueFull() { 65c40c411683da5db1e393e2172a451c3f9c511811Angus Kong return (mMemoryUse >= SAVE_TASK_MEMORY_LIMIT); 66ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 67ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 68fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 69fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong public void addImage(final byte[] data, String title, long date, Location loc, int width, 70b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling int height, int orientation, ExifInterface exif, OnMediaSavedListener l) { 7182d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar addImage(data, title, date, loc, width, height, orientation, exif, l, 72b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling FilmstripItemData.MIME_TYPE_JPEG); 7382d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar } 7482d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar 7582d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar @Override 7682d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar public void addImage(final byte[] data, String title, long date, Location loc, int width, 7782d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar int height, int orientation, ExifInterface exif, OnMediaSavedListener l, 78b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling String mimeType) { 79ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong if (isQueueFull()) { 80ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong Log.e(TAG, "Cannot add image when the queue is full"); 81ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong return; 82ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 8383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong ImageSaveTask t = new ImageSaveTask(data, title, date, 8483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong (loc == null) ? null : new Location(loc), 85b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling width, height, orientation, mimeType, exif, mContentResolver, l); 86ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 87c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse += data.length; 88ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong if (isQueueFull()) { 89ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong onQueueFull(); 90ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 91ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong t.execute(); 92ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 93ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 94fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 95fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong public void addImage(final byte[] data, String title, long date, Location loc, int orientation, 96b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling ExifInterface exif, OnMediaSavedListener l) { 976df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // When dimensions are unknown, pass 0 as width and height, 986df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // and decode image for width and height later in a background thread 99b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling addImage(data, title, date, loc, 0, 0, orientation, exif, l, 100b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling FilmstripItemData.MIME_TYPE_JPEG); 1016df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu } 102fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 103fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong public void addImage(final byte[] data, String title, Location loc, int width, int height, 104b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling int orientation, ExifInterface exif, OnMediaSavedListener l) { 105b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling addImage(data, title, System.currentTimeMillis(), loc, width, height, orientation, exif, l, 106b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling FilmstripItemData.MIME_TYPE_JPEG); 107c40c411683da5db1e393e2172a451c3f9c511811Angus Kong } 108c40c411683da5db1e393e2172a451c3f9c511811Angus Kong 109fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 110b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public void addVideo(String path, ContentValues values, OnMediaSavedListener l) { 11183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // We don't set a queue limit for video saving because the file 11283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // is already in the storage. Only updating the database. 113b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling new VideoSaveTask(path, values, l, mContentResolver).execute(); 11483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 11583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 116fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong @Override 117fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong public void setQueueListener(QueueListener l) { 118fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong mQueueListener = l; 119280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling if (l == null) { 120280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling return; 121280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling } 122d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb l.onQueueStatus(isQueueFull()); 123ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 124ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 125ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private void onQueueFull() { 126280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling if (mQueueListener != null) { 127280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling mQueueListener.onQueueStatus(true); 128280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling } 129ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 130ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 131ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private void onQueueAvailable() { 132280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling if (mQueueListener != null) { 133280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling mQueueListener.onQueueStatus(false); 134280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling } 135ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 136ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 13783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private class ImageSaveTask extends AsyncTask <Void, Void, Uri> { 138280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final byte[] data; 139280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final String title; 140280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final long date; 141280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final Location loc; 142ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong private int width, height; 143280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final int orientation; 14482d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar private final String mimeType; 145280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final ExifInterface exif; 146280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final ContentResolver resolver; 147280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final OnMediaSavedListener listener; 148ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 14983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong public ImageSaveTask(byte[] data, String title, long date, Location loc, 15082d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar int width, int height, int orientation, String mimeType, 15182d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar ExifInterface exif, ContentResolver resolver, 15282d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar OnMediaSavedListener listener) { 153ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.data = data; 154ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.title = title; 155ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.date = date; 156ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.loc = loc; 157ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.width = width; 158ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.height = height; 159ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.orientation = orientation; 16082d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar this.mimeType = mimeType; 1610d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong this.exif = exif; 162ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.resolver = resolver; 163ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong this.listener = listener; 164ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 165ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 166ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 167ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected void onPreExecute() { 168ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong // do nothing. 169ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 170ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 171ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 172ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected Uri doInBackground(Void... v) { 1736df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu if (width == 0 || height == 0) { 1746df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu // Decode bounds 1756df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu BitmapFactory.Options options = new BitmapFactory.Options(); 1766df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu options.inJustDecodeBounds = true; 1776df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu BitmapFactory.decodeByteArray(data, 0, data.length, options); 1786df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu width = options.outWidth; 1796df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu height = options.outHeight; 1806df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu } 181734122e8fe6c621a8510043839f05a0adff4c3a4zafir try { 182734122e8fe6c621a8510043839f05a0adff4c3a4zafir return Storage.addImage( 183734122e8fe6c621a8510043839f05a0adff4c3a4zafir resolver, title, date, loc, orientation, exif, data, width, height, 184734122e8fe6c621a8510043839f05a0adff4c3a4zafir mimeType); 185734122e8fe6c621a8510043839f05a0adff4c3a4zafir } catch (IOException e) { 186734122e8fe6c621a8510043839f05a0adff4c3a4zafir Log.e(TAG, "Failed to write data", e); 187734122e8fe6c621a8510043839f05a0adff4c3a4zafir return null; 188734122e8fe6c621a8510043839f05a0adff4c3a4zafir } 189ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 190ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong 191ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong @Override 192ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong protected void onPostExecute(Uri uri) { 193734122e8fe6c621a8510043839f05a0adff4c3a4zafir if (listener != null) { 194c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong listener.onMediaSaved(uri); 195c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong } 196c40c411683da5db1e393e2172a451c3f9c511811Angus Kong boolean previouslyFull = isQueueFull(); 197c40c411683da5db1e393e2172a451c3f9c511811Angus Kong mMemoryUse -= data.length; 198c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong if (isQueueFull() != previouslyFull) { 199c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong onQueueAvailable(); 200c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong } 201ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 202ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong } 20383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 20483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private class VideoSaveTask extends AsyncTask <Void, Void, Uri> { 20583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong private String path; 206280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final ContentValues values; 207280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final OnMediaSavedListener listener; 208280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling private final ContentResolver resolver; 20983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 210203abe5913394239a1e888d71d56597b68f84f62Andy Huibers public VideoSaveTask(String path, ContentValues values, OnMediaSavedListener l, 211203abe5913394239a1e888d71d56597b68f84f62Andy Huibers ContentResolver r) { 21283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.path = path; 21383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.values = new ContentValues(values); 21483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.listener = l; 21583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong this.resolver = r; 21683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 21783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 21883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong @Override 21983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong protected Uri doInBackground(Void... v) { 22083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Uri uri = null; 22183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong try { 2223973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu Uri videoTable = Uri.parse(VIDEO_BASE_URI); 22383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong uri = resolver.insert(videoTable, values); 22483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 22583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // Rename the video file to the final name. This avoids other 22683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // apps reading incomplete data. We need to do it after we are 22783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // certain that the previous insert to MediaProvider is completed. 22810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers String finalName = values.getAsString(Video.Media.DATA); 2296388e638d36082138f58ad2c7ab8d7645f315ea1Andy Huibers File finalFile = new File(finalName); 2306388e638d36082138f58ad2c7ab8d7645f315ea1Andy Huibers if (new File(path).renameTo(finalFile)) { 23183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong path = finalName; 23283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 23383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong resolver.update(uri, values, null, null); 23483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } catch (Exception e) { 23583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // We failed to insert into the database. This can happen if 23683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong // the SD card is unmounted. 23783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Log.e(TAG, "failed to add video to media store", e); 23883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong uri = null; 23983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } finally { 24083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong Log.v(TAG, "Current video URI: " + uri); 24183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 24283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong return uri; 24383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 24483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong 24583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong @Override 24683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong protected void onPostExecute(Uri uri) { 247c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong if (listener != null) { 248c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong listener.onMediaSaved(uri); 249c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong } 25083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 25183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong } 252ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong} 253