~singpolyma/cheogram-android

66457c9f2ec61953d831b132206e8e06e14313bd — Daniel Gultsch 7 years ago 9b6ae6d
transcode videos before sharing. change storage location
M build.gradle => build.gradle +1 -0
@@ 40,6 40,7 @@ dependencies {
    compile 'org.whispersystems:axolotl-android:1.3.4'
    compile 'com.makeramen:roundedimageview:2.2.0'
    compile "com.wefika:flowlayout:0.4.1"
    compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
}

ext {

M src/main/AndroidManifest.xml => src/main/AndroidManifest.xml +2 -0
@@ 19,6 19,8 @@
        android:name="android.permission.READ_PHONE_STATE"
        tools:node="remove" />

    <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"

M src/main/java/eu/siacs/conversations/persistance/FileBackend.java => src/main/java/eu/siacs/conversations/persistance/FileBackend.java +13 -19
@@ 71,7 71,7 @@ public class FileBackend {
	}

	private void createNoMedia() {
		final File nomedia = new File(getConversationsFileDirectory()+".nomedia");
		final File nomedia = new File(getConversationsDirectory("Files")+".nomedia");
		if (!nomedia.exists()) {
			try {
				nomedia.createNewFile();


@@ 82,7 82,9 @@ public class FileBackend {
	}

	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.setData(Uri.fromFile(file));
			mXmppConnectionService.sendBroadcast(intent);


@@ 118,14 120,16 @@ public class FileBackend {
			file = new DownloadableFile(path);
		} else {
			String mime = message.getMimeType();
			if (mime != null && mime.startsWith("image")) {
				file = new DownloadableFile(getConversationsImageDirectory() + path);
			if (mime != null && mime.startsWith("image/")) {
				file = new DownloadableFile(getConversationsDirectory("Images") + path);
			} else if (mime != null && mime.startsWith("video/")) {
				file = new DownloadableFile(getConversationsDirectory("Videos") + path);
			} else {
				file = new DownloadableFile(getConversationsFileDirectory() + path);
				file = new DownloadableFile(getConversationsDirectory("Files") + path);
			}
		}
		if (encrypted) {
			return new DownloadableFile(getConversationsFileDirectory() + file.getName() + ".pgp");
			return new DownloadableFile(getConversationsDirectory("Files") + file.getName() + ".pgp");
		} else {
			return file;
		}


@@ 154,21 158,11 @@ public class FileBackend {
		return true;
	}

	public String getConversationsFileDirectory() {
	public String getConversationsDirectory(final String type) {
		if (Config.ONLY_INTERNAL_STORAGE) {
			return mXmppConnectionService.getFilesDir().getAbsolutePath() + "/Files/";
			return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/"+type+"/";
		} else {
			return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/";
		}
	}

	public String getConversationsImageDirectory() {
		if (Config.ONLY_INTERNAL_STORAGE) {
			return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/Pictures/";
		} else {
			return Environment.getExternalStoragePublicDirectory(
					Environment.DIRECTORY_PICTURES).getAbsolutePath()
					+ "/Conversations/";
			return Environment.getExternalStorageDirectory() +"/Conversations/Media/Conversations "+type+"/";
		}
	}


M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java => src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +76 -3
@@ 20,6 20,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
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.SessionImpl;
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.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.cert.CertificateException;


@@ 59,6 64,7 @@ import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;

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.ui.SettingsActivity;
import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.ui.UiInformableCallback;
import eu.siacs.conversations.utils.ConversationsFileObserver;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.ExceptionHelper;


@@ 457,10 464,10 @@ public class XmppConnectionService extends Service {
		}
		message.setCounterpart(conversation.getNextCounterpart());
		message.setType(Message.TYPE_FILE);
		final String path = getFileBackend().getOriginalPath(uri);
		mFileAddingExecutor.execute(new Runnable() {
			@Override
			public void run() {

			private void processAsFile() {
				final String path = getFileBackend().getOriginalPath(uri);
				if (path != null) {
					message.setRelativeFilePath(path);
					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();
				}

			}
		});
	}


M src/main/java/eu/siacs/conversations/ui/ConversationActivity.java => src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +18 -1
@@ 1543,9 1543,26 @@ public class ConversationActivity extends XmppActivity
		}
		final Toast prepareFileToast = Toast.makeText(getApplicationContext(),getText(R.string.preparing_file), Toast.LENGTH_LONG);
		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
			public void success(Message message) {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						hideToast();
					}
				});
				hidePrepareFileToast(prepareFileToast);
				xmppConnectionService.sendMessage(message);
			}

M src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java => src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java +12 -3
@@ 59,7 59,17 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
	private Toast mToast;
	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
		public void userInputRequried(PendingIntent pi, Message object) {


@@ 293,8 303,7 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
					} else {
						replaceToast(getString(R.string.preparing_file));
						ShareWithActivity.this.xmppConnectionService
								.attachFileToConversation(conversation, share.uris.get(0),
										attachFileCallback);
								.attachFileToConversation(conversation, share.uris.get(0), attachFileCallback);
					}
				}
			};

A src/main/java/eu/siacs/conversations/ui/UiInformableCallback.java => src/main/java/eu/siacs/conversations/ui/UiInformableCallback.java +5 -0
@@ 0,0 1,5 @@
package eu.siacs.conversations.ui;

public interface UiInformableCallback<T> extends UiCallback<T> {
    void inform(String text);
}

M src/main/res/values/strings.xml => src/main/res/values/strings.xml +1 -0
@@ 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="encrypting_message">Encrypting message</string>
	<string name="not_fetching_history_retention_period">Overstepping local retention period.</string>
	<string name="transcoding_video_progress">Compressing video (%s%% completed)</string>
</resources>

M src/main/res/xml/file_paths.xml => src/main/res/xml/file_paths.xml +3 -2
@@ 1,7 1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <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" />
    <cache-path path="Camera/" name="cam" />
    <cache-path path="Camera/" name="camera" />
</paths>
\ No newline at end of file