transcode videos before sharing. change storage location
This commit is contained in:
		
							parent
							
								
									9b6ae6d75f
								
							
						
					
					
						commit
						66457c9f2e
					
				| @ -40,6 +40,7 @@ dependencies { | |||||||
|     compile 'org.whispersystems:axolotl-android:1.3.4' |     compile 'org.whispersystems:axolotl-android:1.3.4' | ||||||
|     compile 'com.makeramen:roundedimageview:2.2.0' |     compile 'com.makeramen:roundedimageview:2.2.0' | ||||||
|     compile "com.wefika:flowlayout:0.4.1" |     compile "com.wefika:flowlayout:0.4.1" | ||||||
|  |     compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ext { | ext { | ||||||
|  | |||||||
| @ -19,6 +19,8 @@ | |||||||
|         android:name="android.permission.READ_PHONE_STATE" |         android:name="android.permission.READ_PHONE_STATE" | ||||||
|         tools:node="remove" /> |         tools:node="remove" /> | ||||||
| 
 | 
 | ||||||
|  |     <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" /> | ||||||
|  | 
 | ||||||
|     <application |     <application | ||||||
|         android:allowBackup="true" |         android:allowBackup="true" | ||||||
|         android:icon="@drawable/ic_launcher" |         android:icon="@drawable/ic_launcher" | ||||||
|  | |||||||
| @ -71,7 +71,7 @@ public class FileBackend { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void createNoMedia() { | 	private void createNoMedia() { | ||||||
| 		final File nomedia = new File(getConversationsFileDirectory()+".nomedia"); | 		final File nomedia = new File(getConversationsDirectory("Files")+".nomedia"); | ||||||
| 		if (!nomedia.exists()) { | 		if (!nomedia.exists()) { | ||||||
| 			try { | 			try { | ||||||
| 				nomedia.createNewFile(); | 				nomedia.createNewFile(); | ||||||
| @ -82,7 +82,9 @@ public class FileBackend { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void updateMediaScanner(File file) { | 	public void updateMediaScanner(File file) { | ||||||
| 		if (file.getAbsolutePath().startsWith(getConversationsImageDirectory())) { | 		String path = file.getAbsolutePath(); | ||||||
|  | 		if (!path.startsWith(getConversationsDirectory("Files"))) { | ||||||
|  | 			new File(Environment.getExternalStorageDirectory()+"/Conversations/.nomedia").delete(); | ||||||
| 			Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); | 			Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); | ||||||
| 			intent.setData(Uri.fromFile(file)); | 			intent.setData(Uri.fromFile(file)); | ||||||
| 			mXmppConnectionService.sendBroadcast(intent); | 			mXmppConnectionService.sendBroadcast(intent); | ||||||
| @ -118,14 +120,16 @@ public class FileBackend { | |||||||
| 			file = new DownloadableFile(path); | 			file = new DownloadableFile(path); | ||||||
| 		} else { | 		} else { | ||||||
| 			String mime = message.getMimeType(); | 			String mime = message.getMimeType(); | ||||||
| 			if (mime != null && mime.startsWith("image")) { | 			if (mime != null && mime.startsWith("image/")) { | ||||||
| 				file = new DownloadableFile(getConversationsImageDirectory() + path); | 				file = new DownloadableFile(getConversationsDirectory("Images") + path); | ||||||
|  | 			} else if (mime != null && mime.startsWith("video/")) { | ||||||
|  | 				file = new DownloadableFile(getConversationsDirectory("Videos") + path); | ||||||
| 			} else { | 			} else { | ||||||
| 				file = new DownloadableFile(getConversationsFileDirectory() + path); | 				file = new DownloadableFile(getConversationsDirectory("Files") + path); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (encrypted) { | 		if (encrypted) { | ||||||
| 			return new DownloadableFile(getConversationsFileDirectory() + file.getName() + ".pgp"); | 			return new DownloadableFile(getConversationsDirectory("Files") + file.getName() + ".pgp"); | ||||||
| 		} else { | 		} else { | ||||||
| 			return file; | 			return file; | ||||||
| 		} | 		} | ||||||
| @ -154,21 +158,11 @@ public class FileBackend { | |||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public String getConversationsFileDirectory() { | 	public String getConversationsDirectory(final String type) { | ||||||
| 		if (Config.ONLY_INTERNAL_STORAGE) { | 		if (Config.ONLY_INTERNAL_STORAGE) { | ||||||
| 			return mXmppConnectionService.getFilesDir().getAbsolutePath() + "/Files/"; | 			return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/"+type+"/"; | ||||||
| 		} else { | 		} else { | ||||||
| 			return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/"; | 			return Environment.getExternalStorageDirectory() +"/Conversations/Media/Conversations "+type+"/"; | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public String getConversationsImageDirectory() { |  | ||||||
| 		if (Config.ONLY_INTERNAL_STORAGE) { |  | ||||||
| 			return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/Pictures/"; |  | ||||||
| 		} else { |  | ||||||
| 			return Environment.getExternalStoragePublicDirectory( |  | ||||||
| 					Environment.DIRECTORY_PICTURES).getAbsolutePath() |  | ||||||
| 					+ "/Conversations/"; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ import android.os.Build; | |||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.os.Environment; | import android.os.Environment; | ||||||
| import android.os.IBinder; | import android.os.IBinder; | ||||||
|  | import android.os.ParcelFileDescriptor; | ||||||
| import android.os.PowerManager; | import android.os.PowerManager; | ||||||
| import android.os.PowerManager.WakeLock; | import android.os.PowerManager.WakeLock; | ||||||
| import android.os.SystemClock; | import android.os.SystemClock; | ||||||
| @ -37,11 +38,15 @@ import net.java.otr4j.session.Session; | |||||||
| import net.java.otr4j.session.SessionID; | import net.java.otr4j.session.SessionID; | ||||||
| import net.java.otr4j.session.SessionImpl; | import net.java.otr4j.session.SessionImpl; | ||||||
| import net.java.otr4j.session.SessionStatus; | import net.java.otr4j.session.SessionStatus; | ||||||
|  | import net.ypresto.androidtranscoder.MediaTranscoder; | ||||||
|  | import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets; | ||||||
| 
 | 
 | ||||||
| import org.openintents.openpgp.IOpenPgpService2; | import org.openintents.openpgp.IOpenPgpService2; | ||||||
| import org.openintents.openpgp.util.OpenPgpApi; | import org.openintents.openpgp.util.OpenPgpApi; | ||||||
| import org.openintents.openpgp.util.OpenPgpServiceConnection; | import org.openintents.openpgp.util.OpenPgpServiceConnection; | ||||||
| 
 | 
 | ||||||
|  | import java.io.FileDescriptor; | ||||||
|  | import java.io.FileNotFoundException; | ||||||
| import java.math.BigInteger; | import java.math.BigInteger; | ||||||
| import java.security.SecureRandom; | import java.security.SecureRandom; | ||||||
| import java.security.cert.CertificateException; | import java.security.cert.CertificateException; | ||||||
| @ -59,6 +64,7 @@ import java.util.ListIterator; | |||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.concurrent.CopyOnWriteArrayList; | import java.util.concurrent.CopyOnWriteArrayList; | ||||||
|  | import java.util.concurrent.ExecutionException; | ||||||
| import java.util.concurrent.atomic.AtomicLong; | import java.util.concurrent.atomic.AtomicLong; | ||||||
| 
 | 
 | ||||||
| import de.duenndns.ssl.MemorizingTrustManager; | import de.duenndns.ssl.MemorizingTrustManager; | ||||||
| @ -97,6 +103,7 @@ import eu.siacs.conversations.persistance.DatabaseBackend; | |||||||
| import eu.siacs.conversations.persistance.FileBackend; | import eu.siacs.conversations.persistance.FileBackend; | ||||||
| import eu.siacs.conversations.ui.SettingsActivity; | import eu.siacs.conversations.ui.SettingsActivity; | ||||||
| import eu.siacs.conversations.ui.UiCallback; | import eu.siacs.conversations.ui.UiCallback; | ||||||
|  | import eu.siacs.conversations.ui.UiInformableCallback; | ||||||
| import eu.siacs.conversations.utils.ConversationsFileObserver; | import eu.siacs.conversations.utils.ConversationsFileObserver; | ||||||
| import eu.siacs.conversations.utils.CryptoHelper; | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
| import eu.siacs.conversations.utils.ExceptionHelper; | import eu.siacs.conversations.utils.ExceptionHelper; | ||||||
| @ -457,10 +464,10 @@ public class XmppConnectionService extends Service { | |||||||
| 		} | 		} | ||||||
| 		message.setCounterpart(conversation.getNextCounterpart()); | 		message.setCounterpart(conversation.getNextCounterpart()); | ||||||
| 		message.setType(Message.TYPE_FILE); | 		message.setType(Message.TYPE_FILE); | ||||||
| 		final String path = getFileBackend().getOriginalPath(uri); |  | ||||||
| 		mFileAddingExecutor.execute(new Runnable() { | 		mFileAddingExecutor.execute(new Runnable() { | ||||||
| 			@Override | 
 | ||||||
| 			public void run() { | 			private void processAsFile() { | ||||||
|  | 				final String path = getFileBackend().getOriginalPath(uri); | ||||||
| 				if (path != null) { | 				if (path != null) { | ||||||
| 					message.setRelativeFilePath(path); | 					message.setRelativeFilePath(path); | ||||||
| 					getFileBackend().updateFileParams(message); | 					getFileBackend().updateFileParams(message); | ||||||
| @ -488,6 +495,72 @@ public class XmppConnectionService extends Service { | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			private void processAsVideo() throws FileNotFoundException { | ||||||
|  | 				Log.d(Config.LOGTAG,"processing file as video"); | ||||||
|  | 				message.setRelativeFilePath(message.getUuid() + ".mp4"); | ||||||
|  | 				final DownloadableFile file = getFileBackend().getFile(message); | ||||||
|  | 				file.getParentFile().mkdirs(); | ||||||
|  | 				ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r"); | ||||||
|  | 				FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); | ||||||
|  | 				final ArrayList<Integer> progressTracker = new ArrayList<>(); | ||||||
|  | 				final UiInformableCallback<Message> informableCallback; | ||||||
|  | 				if (callback instanceof UiInformableCallback) { | ||||||
|  | 					informableCallback = (UiInformableCallback<Message>) callback; | ||||||
|  | 				} else { | ||||||
|  | 					informableCallback = null; | ||||||
|  | 				} | ||||||
|  | 				MediaTranscoder.Listener listener = new MediaTranscoder.Listener() { | ||||||
|  | 					@Override | ||||||
|  | 					public void onTranscodeProgress(double progress) { | ||||||
|  | 						int p = ((int) Math.round(progress * 100) / 20) * 20; | ||||||
|  | 						if (!progressTracker.contains(p) && p != 100 && p != 0) { | ||||||
|  | 							progressTracker.add(p); | ||||||
|  | 							if (informableCallback != null) { | ||||||
|  | 
 | ||||||
|  | 								informableCallback.inform(getString(R.string.transcoding_video_progress, p)); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					@Override | ||||||
|  | 					public void onTranscodeCompleted() { | ||||||
|  | 						if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { | ||||||
|  | 							getPgpEngine().encrypt(message, callback); | ||||||
|  | 						} else { | ||||||
|  | 							callback.success(message); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					@Override | ||||||
|  | 					public void onTranscodeCanceled() { | ||||||
|  | 						processAsFile(); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					@Override | ||||||
|  | 					public void onTranscodeFailed(Exception e) { | ||||||
|  | 						Log.d(Config.LOGTAG,"video transcoding failed "+e.getMessage()); | ||||||
|  | 						processAsFile(); | ||||||
|  | 					} | ||||||
|  | 				}; | ||||||
|  | 				MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(), | ||||||
|  | 						MediaFormatStrategyPresets.createAndroid720pStrategy(), listener); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			@Override | ||||||
|  | 			public void run() { | ||||||
|  | 				final String mimeType = MimeUtils.guessMimeTypeFromUri(XmppConnectionService.this, uri); | ||||||
|  | 				if (mimeType != null && mimeType.startsWith("video/") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { | ||||||
|  | 					try { | ||||||
|  | 						processAsVideo(); | ||||||
|  | 					} catch (Throwable e) { | ||||||
|  | 						processAsFile(); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					processAsFile(); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1543,9 +1543,26 @@ public class ConversationActivity extends XmppActivity | |||||||
| 		} | 		} | ||||||
| 		final Toast prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_file), Toast.LENGTH_LONG); | 		final Toast prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_file), Toast.LENGTH_LONG); | ||||||
| 		prepareFileToast.show(); | 		prepareFileToast.show(); | ||||||
| 		xmppConnectionService.attachFileToConversation(conversation, uri, new UiCallback<Message>() { | 		xmppConnectionService.attachFileToConversation(conversation, uri, new UiInformableCallback<Message>() { | ||||||
|  | 			@Override | ||||||
|  | 			public void inform(final String text) { | ||||||
|  | 				hidePrepareFileToast(prepareFileToast); | ||||||
|  | 				runOnUiThread(new Runnable() { | ||||||
|  | 					@Override | ||||||
|  | 					public void run() { | ||||||
|  | 						replaceToast(text); | ||||||
|  | 					} | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			@Override | 			@Override | ||||||
| 			public void success(Message message) { | 			public void success(Message message) { | ||||||
|  | 				runOnUiThread(new Runnable() { | ||||||
|  | 					@Override | ||||||
|  | 					public void run() { | ||||||
|  | 						hideToast(); | ||||||
|  | 					} | ||||||
|  | 				}); | ||||||
| 				hidePrepareFileToast(prepareFileToast); | 				hidePrepareFileToast(prepareFileToast); | ||||||
| 				xmppConnectionService.sendMessage(message); | 				xmppConnectionService.sendMessage(message); | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -59,7 +59,17 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer | |||||||
| 	private Toast mToast; | 	private Toast mToast; | ||||||
| 	private AtomicInteger attachmentCounter = new AtomicInteger(0); | 	private AtomicInteger attachmentCounter = new AtomicInteger(0); | ||||||
| 
 | 
 | ||||||
| 	private UiCallback<Message> attachFileCallback = new UiCallback<Message>() { | 	private UiInformableCallback<Message> attachFileCallback = new UiInformableCallback<Message>() { | ||||||
|  | 
 | ||||||
|  | 		@Override | ||||||
|  | 		public void inform(final String text) { | ||||||
|  | 			runOnUiThread(new Runnable() { | ||||||
|  | 				@Override | ||||||
|  | 				public void run() { | ||||||
|  | 					replaceToast(text); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		@Override | 		@Override | ||||||
| 		public void userInputRequried(PendingIntent pi, Message object) { | 		public void userInputRequried(PendingIntent pi, Message object) { | ||||||
| @ -293,8 +303,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer | |||||||
| 					} else { | 					} else { | ||||||
| 						replaceToast(getString(R.string.preparing_file)); | 						replaceToast(getString(R.string.preparing_file)); | ||||||
| 						ShareWithActivity.this.xmppConnectionService | 						ShareWithActivity.this.xmppConnectionService | ||||||
| 								.attachFileToConversation(conversation, share.uris.get(0), | 								.attachFileToConversation(conversation, share.uris.get(0), attachFileCallback); | ||||||
| 										attachFileCallback); |  | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}; | 			}; | ||||||
|  | |||||||
| @ -0,0 +1,5 @@ | |||||||
|  | package eu.siacs.conversations.ui; | ||||||
|  | 
 | ||||||
|  | public interface UiInformableCallback<T> extends UiCallback<T> { | ||||||
|  |     void inform(String text); | ||||||
|  | } | ||||||
| @ -732,4 +732,5 @@ | |||||||
| 	<string name="pref_automatically_delete_messages_description">Automatically delete messages from this device that are older than the configured time frame.</string> | 	<string name="pref_automatically_delete_messages_description">Automatically delete messages from this device that are older than the configured time frame.</string> | ||||||
| 	<string name="encrypting_message">Encrypting message</string> | 	<string name="encrypting_message">Encrypting message</string> | ||||||
| 	<string name="not_fetching_history_retention_period">Overstepping local retention period.</string> | 	<string name="not_fetching_history_retention_period">Overstepping local retention period.</string> | ||||||
|  | 	<string name="transcoding_video_progress">Compressing video (%s%% completed)</string> | ||||||
| </resources> | </resources> | ||||||
|  | |||||||
| @ -1,7 +1,8 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <paths> | <paths> | ||||||
|     <external-path name="external" path="/"/> |     <external-path name="external" path="/"/> | ||||||
|     <files-path path="Pictures/" name="pics" /> |     <files-path path="Images/" name="pictures" /> | ||||||
|  |     <files-path path="Videos" name="videos"/> | ||||||
|     <files-path path="Files/" name="files" /> |     <files-path path="Files/" name="files" /> | ||||||
|     <cache-path path="Camera/" name="cam" /> |     <cache-path path="Camera/" name="camera" /> | ||||||
| </paths> | </paths> | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch