1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.util; 18 19import android.content.ContentResolver; 20import android.content.ContentValues; 21import android.database.Cursor; 22import android.media.MediaMetadataRetriever; 23import android.net.Uri; 24import android.os.Environment; 25import android.provider.MediaStore.Video; 26import android.provider.MediaStore.Video.VideoColumns; 27 28import com.android.gallery3d.filtershow.tools.SaveImage.ContentResolverQueryCallback; 29 30import java.io.File; 31import java.text.SimpleDateFormat; 32import java.util.Date; 33 34public class SaveVideoFileUtils { 35 // This function can decide which folder to save the video file, and generate 36 // the needed information for the video file including filename. 37 public static SaveVideoFileInfo getDstMp4FileInfo(String fileNameFormat, 38 ContentResolver contentResolver, Uri uri, String defaultFolderName) { 39 SaveVideoFileInfo dstFileInfo = new SaveVideoFileInfo(); 40 // Use the default save directory if the source directory cannot be 41 // saved. 42 dstFileInfo.mDirectory = getSaveDirectory(contentResolver, uri); 43 if ((dstFileInfo.mDirectory == null) || !dstFileInfo.mDirectory.canWrite()) { 44 dstFileInfo.mDirectory = new File(Environment.getExternalStorageDirectory(), 45 BucketNames.DOWNLOAD); 46 dstFileInfo.mFolderName = defaultFolderName; 47 } else { 48 dstFileInfo.mFolderName = dstFileInfo.mDirectory.getName(); 49 } 50 dstFileInfo.mFileName = new SimpleDateFormat(fileNameFormat).format( 51 new Date(System.currentTimeMillis())); 52 53 dstFileInfo.mFile = new File(dstFileInfo.mDirectory, dstFileInfo.mFileName + ".mp4"); 54 return dstFileInfo; 55 } 56 57 private static void querySource(ContentResolver contentResolver, Uri uri, 58 String[] projection, ContentResolverQueryCallback callback) { 59 Cursor cursor = null; 60 try { 61 cursor = contentResolver.query(uri, projection, null, null, null); 62 if ((cursor != null) && cursor.moveToNext()) { 63 callback.onCursorResult(cursor); 64 } 65 } catch (Exception e) { 66 // Ignore error for lacking the data column from the source. 67 } finally { 68 if (cursor != null) { 69 cursor.close(); 70 } 71 } 72 } 73 74 private static File getSaveDirectory(ContentResolver contentResolver, Uri uri) { 75 final File[] dir = new File[1]; 76 querySource(contentResolver, uri, 77 new String[] { VideoColumns.DATA }, 78 new ContentResolverQueryCallback() { 79 @Override 80 public void onCursorResult(Cursor cursor) { 81 dir[0] = new File(cursor.getString(0)).getParentFile(); 82 } 83 }); 84 return dir[0]; 85 } 86 87 88 /** 89 * Insert the content (saved file) with proper video properties. 90 */ 91 public static Uri insertContent(SaveVideoFileInfo mDstFileInfo, 92 ContentResolver contentResolver, Uri uri ) { 93 long nowInMs = System.currentTimeMillis(); 94 long nowInSec = nowInMs / 1000; 95 final ContentValues values = new ContentValues(13); 96 values.put(Video.Media.TITLE, mDstFileInfo.mFileName); 97 values.put(Video.Media.DISPLAY_NAME, mDstFileInfo.mFile.getName()); 98 values.put(Video.Media.MIME_TYPE, "video/mp4"); 99 values.put(Video.Media.DATE_TAKEN, nowInMs); 100 values.put(Video.Media.DATE_MODIFIED, nowInSec); 101 values.put(Video.Media.DATE_ADDED, nowInSec); 102 values.put(Video.Media.DATA, mDstFileInfo.mFile.getAbsolutePath()); 103 values.put(Video.Media.SIZE, mDstFileInfo.mFile.length()); 104 int durationMs = retriveVideoDurationMs(mDstFileInfo.mFile.getPath()); 105 values.put(Video.Media.DURATION, durationMs); 106 // Copy the data taken and location info from src. 107 String[] projection = new String[] { 108 VideoColumns.DATE_TAKEN, 109 VideoColumns.LATITUDE, 110 VideoColumns.LONGITUDE, 111 VideoColumns.RESOLUTION, 112 }; 113 114 // Copy some info from the source file. 115 querySource(contentResolver, uri, projection, 116 new ContentResolverQueryCallback() { 117 @Override 118 public void onCursorResult(Cursor cursor) { 119 long timeTaken = cursor.getLong(0); 120 if (timeTaken > 0) { 121 values.put(Video.Media.DATE_TAKEN, timeTaken); 122 } 123 double latitude = cursor.getDouble(1); 124 double longitude = cursor.getDouble(2); 125 // TODO: Change || to && after the default location 126 // issue is 127 // fixed. 128 if ((latitude != 0f) || (longitude != 0f)) { 129 values.put(Video.Media.LATITUDE, latitude); 130 values.put(Video.Media.LONGITUDE, longitude); 131 } 132 values.put(Video.Media.RESOLUTION, cursor.getString(3)); 133 134 } 135 }); 136 137 return contentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, values); 138 } 139 140 public static int retriveVideoDurationMs(String path) { 141 int durationMs = 0; 142 // Calculate the duration of the destination file. 143 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 144 retriever.setDataSource(path); 145 String duration = retriever.extractMetadata( 146 MediaMetadataRetriever.METADATA_KEY_DURATION); 147 if (duration != null) { 148 durationMs = Integer.parseInt(duration); 149 } 150 retriever.release(); 151 return durationMs; 152 } 153 154} 155