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