/**
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.waz.zclient.pages.main.conversation;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import com.waz.utils.wrappers.AndroidURI;
import com.waz.utils.wrappers.AndroidURIUtil;
import com.waz.utils.wrappers.URI;
import com.waz.zclient.BuildConfig;
import com.waz.zclient.utils.PermissionUtils;
import timber.log.Timber;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class AssetIntentsManager {
private static final String SAVED_STATE_PENDING_URI = "SAVED_STATE_PENDING_URI";
private static final String[] CAMERA_PERMISSIONS = new String[] {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static final String INTENT_GALLERY_TYPE = "image/*";
private final PackageManager pm;
@TargetApi(19)
private static String openDocumentAction() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT;
}
private URI pendingFileUri;
private Callback callback;
public AssetIntentsManager(Activity activity, Callback callback, Bundle savedInstanceState) {
setCallback(callback);
if (savedInstanceState != null) {
Uri uri = savedInstanceState.getParcelable(SAVED_STATE_PENDING_URI);
if (uri != null) {
pendingFileUri = new AndroidURI(uri);
}
}
pm = activity.getPackageManager();
}
public void setCallback(Callback callback) {
this.callback = callback;
}
private void openDocument(String mimeType, IntentType tpe) {
if (BuildConfig.IS_TEST_GALLERY_ALLOWED) {
// trying to load file from testing gallery,
// this is needed because we are not able to override DocumentsUI on some android versions.
Intent intent = new Intent("com.wire.testing.GET_DOCUMENT").setType(mimeType);
if (!pm.queryIntentActivities(intent, PackageManager.MATCH_ALL).isEmpty()) {
callback.openIntent(intent, tpe);
return;
}
Timber.i("Did not resolve testing gallery for intent: %s", intent.toString());
}
callback.openIntent(new Intent(openDocumentAction()).setType(mimeType).addCategory(Intent.CATEGORY_OPENABLE), tpe);
}
public void openFileSharing() {
openDocument("*/*", IntentType.FILE_SHARING);
}
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
pendingFileUri = getOutputMediaFileUri(IntentType.CAMERA);
intent.putExtra(MediaStore.EXTRA_OUTPUT, AndroidURIUtil.unwrap(pendingFileUri));
callback.openIntent(intent, IntentType.CAMERA);
}
public void maybeCaptureVideo(Activity activity, IntentType type) {
if (PermissionUtils.hasSelfPermissions(activity, CAMERA_PERMISSIONS)) {
captureVideo(type);
} else {
ActivityCompat.requestPermissions(activity, CAMERA_PERMISSIONS, type.permissionCode);
}
}
private void captureVideo(IntentType type) {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
pendingFileUri = getOutputMediaFileUri(IntentType.VIDEO);
intent.putExtra(MediaStore.EXTRA_OUTPUT, AndroidURIUtil.unwrap(pendingFileUri));
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
}
callback.openIntent(intent, type);
}
public void openGallery() {
openDocument(INTENT_GALLERY_TYPE, IntentType.GALLERY);
}
public void openGalleryForSketch() {
openDocument(INTENT_GALLERY_TYPE, IntentType.SKETCH_FROM_GALLERY);
}
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (callback == null) {
throw new IllegalStateException("A callback must be set!");
}
IntentType type = IntentType.get(requestCode);
if (type == IntentType.UNKOWN) {
return false;
}
if (resultCode == Activity.RESULT_CANCELED) {
callback.onCanceled(type);
return true;
}
if (resultCode != Activity.RESULT_OK) {
callback.onFailed(type);
return true;
}
File possibleFile = null;
if (pendingFileUri != null) {
possibleFile = new File(pendingFileUri.getPath());
}
if ((type == IntentType.CAMERA || type == IntentType.VIDEO || type == IntentType.VIDEO_CURSOR_BUTTON) &&
possibleFile != null &&
possibleFile.exists() &&
possibleFile.length() > 0) {
callback.onDataReceived(type, pendingFileUri);
pendingFileUri = null;
} else if (data != null) {
URI uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
uri = AndroidURIUtil.parse(data.getDataString());
} else {
uri = new AndroidURI(data.getData());
}
if (uri == null) {
callback.onFailed(type);
} else {
callback.onDataReceived(type, uri);
}
} else {
callback.onFailed(type);
}
return true;
}
/**
* Create a file Uri for saving an image or video
*
* @param type
*/
private static URI getOutputMediaFileUri(IntentType type) {
File file = getOutputMediaFile(type);
return file != null ? AndroidURIUtil.fromFile(file) : null;
}
/**
* Create a File for saving an image or video
*
* @param type
*/
private static File getOutputMediaFile(IntentType type) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "WIRE_MEDIA");
if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
return null;
}
java.util.Date date = new java.util.Date();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(date.getTime());
switch (type) {
case VIDEO_CURSOR_BUTTON:
case VIDEO:
return new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4");
case CAMERA:
return new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
}
return null;
}
public boolean onRequestPermissionsResult(int requestCode, int[] grantResults) {
IntentType type = IntentType.getByPermissionCode(requestCode);
if (type == IntentType.UNKOWN) {
return false;
}
if (!PermissionUtils.verifyPermissions(grantResults)) {
callback.onPermissionFailed(type);
return true;
}
switch (type) {
case GALLERY:
return true;
case VIDEO_CURSOR_BUTTON:
case VIDEO:
captureVideo(type);
return true;
case CAMERA:
captureImage();
return true;
default:
return false;
}
}
public enum IntentType {
UNKOWN(-1, -1),
GALLERY(9411, 8411),
SKETCH_FROM_GALLERY(9416, 8416),
VIDEO(9412, 8412),
VIDEO_CURSOR_BUTTON(9415, 8415),
CAMERA(9413, 8413),
FILE_SHARING(9414, 8414);
public int requestCode;
private int permissionCode;
IntentType(int requestCode, int permissionCode) {
this.requestCode = requestCode;
this.permissionCode = permissionCode;
}
public static IntentType get(int requestCode) {
if (requestCode == GALLERY.requestCode) {
return GALLERY;
}
if (requestCode == SKETCH_FROM_GALLERY.requestCode) {
return SKETCH_FROM_GALLERY;
}
if (requestCode == CAMERA.requestCode) {
return CAMERA;
}
if (requestCode == VIDEO.requestCode) {
return VIDEO;
}
if (requestCode == VIDEO_CURSOR_BUTTON.requestCode) {
return VIDEO_CURSOR_BUTTON;
}
if (requestCode == FILE_SHARING.requestCode) {
return FILE_SHARING;
}
return UNKOWN;
}
public static IntentType getByPermissionCode(int permissionCode) {
if (permissionCode == GALLERY.permissionCode) {
return GALLERY;
}
if (permissionCode == CAMERA.permissionCode) {
return CAMERA;
}
if (permissionCode == VIDEO.permissionCode) {
return VIDEO;
}
if (permissionCode == VIDEO_CURSOR_BUTTON.permissionCode) {
return VIDEO_CURSOR_BUTTON;
}
if (permissionCode == FILE_SHARING.permissionCode) {
return FILE_SHARING;
}
return UNKOWN;
}
}
public void onSaveInstanceState(Bundle outState) {
if (pendingFileUri != null) {
outState.putParcelable(SAVED_STATE_PENDING_URI, AndroidURIUtil.unwrap(pendingFileUri));
}
}
public interface Callback {
void onDataReceived(IntentType type, URI uri);
void onCanceled(IntentType type);
void onFailed(IntentType type);
void openIntent(Intent intent, AssetIntentsManager.IntentType intentType);
void onPermissionFailed(IntentType type);
}
}