1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2024-11-22 04:12:08 +01:00

Update opoc and it's license headers

This commit is contained in:
Gregor Santner 2018-10-01 21:12:17 +02:00
parent 1129f1848a
commit 2289c04f0f
11 changed files with 381 additions and 56 deletions

View file

@ -93,8 +93,8 @@ public class SimpleMarkdownParser {
.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<img src=\\'$2\\' alt='$1' />") // img .replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<img src=\\'$2\\' alt='$1' />") // img
.replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img) .replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img)
.replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img) .replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img)
.replaceAll("(?m)^([-*] )(.*)$", "<font color='#000001'>&#8226;</font> $2 ") // unordered list + end line .replaceAll("(?m)^[-*] (.*)$", "<font color='#000001'>&#8226;</font> $1 ") // unordered list + end line
.replaceAll("(?m)^ (-|\\*) ([^<]*)$", "&nbsp;&nbsp;<font color='#000001'>&#8226;</font> $2 ") // unordered list2 + end line .replaceAll("(?m)^ [-*] (.*)$", "&nbsp;&nbsp;<font color='#000001'>&#8226;</font> $1 ") // unordered list2 + end line
.replaceAll("`([^<]*)`", "<code>$1</code>") // code .replaceAll("`([^<]*)`", "<code>$1</code>") // code
.replace("\\*", "") // temporary replace escaped star symbol .replace("\\*", "") // temporary replace escaped star symbol
.replaceAll("(?m)\\*\\*(.*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star) .replaceAll("(?m)\\*\\*(.*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star)
@ -111,6 +111,7 @@ public class SimpleMarkdownParser {
public String filter(String text) { public String filter(String text) {
text = text text = text
.replace("New:", "<font color='#276230'>New:</font>") .replace("New:", "<font color='#276230'>New:</font>")
.replace("New features:", "<font color='#276230'>New:</font>")
.replace("Added:", "<font color='#276230'>Added:</font>") .replace("Added:", "<font color='#276230'>Added:</font>")
.replace("Add:", "<font color='#276230'>Add:</font>") .replace("Add:", "<font color='#276230'>Add:</font>")
.replace("Fixed:", "<font color='#005688'>Fixed:</font>") .replace("Fixed:", "<font color='#005688'>Fixed:</font>")

View file

@ -44,6 +44,7 @@ import android.text.TextUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.List; import java.util.List;
@ -512,4 +513,15 @@ public class SharedPreferencesPropertyBackend implements PropertyBackend<String,
setStringListOne(key, value, _prefApp); setStringListOne(key, value, _prefApp);
return this; return this;
} }
/**
* A method to determine if current hour is between begin and end.
* This is especially useful for time-based light/dark mode
*/
public boolean isCurrentHourOfDayBetween(int begin, int end) {
begin = (begin >= 23 || begin < 0) ? 0 : begin;
end = (end >= 23 || end < 0) ? 0 : end;
int h = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
return h >= begin && h <= end;
}
} }

View file

@ -11,6 +11,7 @@
package net.gsantner.opoc.ui; package net.gsantner.opoc.ui;
import android.app.Activity; import android.app.Activity;
import android.graphics.Typeface;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@ -23,6 +24,7 @@ import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Filter; import android.widget.Filter;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -76,10 +78,10 @@ public class SearchOrCustomTextDialog {
TextView textView = (TextView) super.getView(pos, convertView, parent); TextView textView = (TextView) super.getView(pos, convertView, parent);
String text = textView.getText().toString(); String text = textView.getText().toString();
textView.setTextColor(dopt.textColor); boolean hl = dopt.highlightData.contains(text);
if (dopt.highlightData.contains(text)) { textView.setTextColor(hl ? dopt.highlightColor : dopt.textColor);
textView.setTextColor(dopt.highlightColor); textView.setTypeface(null, hl ? Typeface.BOLD : Typeface.NORMAL);
}
return textView; return textView;
} }
@ -184,6 +186,9 @@ public class SearchOrCustomTextDialog {
return false; return false;
}); });
if (dialog.getWindow() != null) {
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
dialog.show(); dialog.show();
} }
} }

View file

@ -3,17 +3,20 @@
* Maintained by Gregor Santner, 2016- * Maintained by Gregor Santner, 2016-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
@ -174,4 +177,12 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
_activity.getWindow().setStatusBarColor(color); _activity.getWindow().setStatusBarColor(color);
} }
} }
public void setLauncherActivityEnabled(Class activityClass, boolean enable) {
Context context = _context.getApplicationContext();
PackageManager pkg = context.getPackageManager();
ComponentName component = new ComponentName(context, activityClass);
pkg.setComponentEnabledSetting(component, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED
, PackageManager.DONT_KILL_APP);
}
} }

View file

@ -3,9 +3,9 @@
* Maintained by Gregor Santner, 2018- * Maintained by Gregor Santner, 2018-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;

View file

@ -3,9 +3,9 @@
* Maintained by Gregor Santner, 2016- * Maintained by Gregor Santner, 2016-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;
@ -167,7 +167,7 @@ public class ContextUtils {
public String getAppVersionName() { public String getAppVersionName() {
try { try {
PackageManager manager = _context.getPackageManager(); PackageManager manager = _context.getPackageManager();
PackageInfo info = manager.getPackageInfo(getPackageName(), 0); PackageInfo info = manager.getPackageInfo(getPackageIdManifest(), 0);
return info.versionName; return info.versionName;
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
@ -178,7 +178,7 @@ public class ContextUtils {
public String getAppInstallationSource() { public String getAppInstallationSource() {
String src = null; String src = null;
try { try {
src = _context.getPackageManager().getInstallerPackageName(getPackageName()); src = _context.getPackageManager().getInstallerPackageName(getPackageIdManifest());
} catch (Exception ignored) { } catch (Exception ignored) {
} }
if (TextUtils.isEmpty(src)) { if (TextUtils.isEmpty(src)) {
@ -224,13 +224,20 @@ public class ContextUtils {
} }
/** /**
* Get this apps package name. The builtin method may fail when used with flavors * Get the apps base packagename, which is equal with all build flavors and variants
*/ */
public String getPackageName() { public String getPackageIdManifest() {
String pkg = rstr("manifest_package_id"); String pkg = rstr("manifest_package_id");
return pkg != null ? pkg : _context.getPackageName(); return pkg != null ? pkg : _context.getPackageName();
} }
/**
* Get this apps package name, returns the flavor specific package name.
*/
public String getPackageIdReal() {
return _context.getPackageName();
}
/** /**
* Get field from ${applicationId}.BuildConfig * Get field from ${applicationId}.BuildConfig
* May be helpful in libraries, where a access to * May be helpful in libraries, where a access to
@ -240,7 +247,7 @@ public class ContextUtils {
* Falls back to applicationId of the app which may differ from manifest. * Falls back to applicationId of the app which may differ from manifest.
*/ */
public Object getBuildConfigValue(String fieldName) { public Object getBuildConfigValue(String fieldName) {
String pkg = getPackageName() + ".BuildConfig"; String pkg = getPackageIdManifest() + ".BuildConfig";
try { try {
Class<?> c = Class.forName(pkg); Class<?> c = Class.forName(pkg);
return c.getField(fieldName).get(null); return c.getField(fieldName).get(null);

View file

@ -3,9 +3,9 @@
* Maintained by Gregor Santner, 2017- * Maintained by Gregor Santner, 2017-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;
@ -397,7 +397,8 @@ public class FileUtils {
} }
public static boolean isTextFile(File file) { public static boolean isTextFile(File file) {
return getMimeType(file).startsWith("text/"); String mime = getMimeType(file);
return mime != null && mime.startsWith("text/");
} }
/** /**

View file

@ -3,9 +3,9 @@
* Maintained by Gregor Santner, 2017- * Maintained by Gregor Santner, 2017-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;

View file

@ -3,9 +3,9 @@
* Maintained by Gregor Santner, 2017- * Maintained by Gregor Santner, 2017-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;

View file

@ -3,17 +3,22 @@
* Maintained by Gregor Santner, 2017- * Maintained by Gregor Santner, 2017-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 * https://github.com/gsantner/opoc/#licensing
* *
#########################################################*/ #########################################################*/
package net.gsantner.opoc.util; package net.gsantner.opoc.util;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ClipData; import android.content.ClipData;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
@ -21,14 +26,18 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.print.PrintAttributes; import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter; import android.print.PrintDocumentAdapter;
import android.print.PrintJob; import android.print.PrintJob;
import android.print.PrintManager; import android.print.PrintManager;
import android.provider.CalendarContract;
import android.provider.MediaStore;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.support.v4.content.FileProvider; import android.support.v4.content.FileProvider;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.content.pm.ShortcutInfoCompat; import android.support.v4.content.pm.ShortcutInfoCompat;
import android.support.v4.content.pm.ShortcutManagerCompat; import android.support.v4.content.pm.ShortcutManagerCompat;
import android.support.v4.graphics.drawable.IconCompat; import android.support.v4.graphics.drawable.IconCompat;
@ -38,16 +47,22 @@ import android.view.View;
import android.webkit.WebView; import android.webkit.WebView;
import java.io.File; import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Random; import java.util.Random;
import static android.app.Activity.RESULT_OK;
/** /**
* A utility class to ease information sharing on Android * A utility class to ease information sharing on Android.
* Also allows to parse/fetch information out of shared information * Also allows to parse/fetch information out of shared information.
* (M)Permissions are not checked, wrap ShareUtils methods if neccessary
*/ */
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess", "SameParameterValue", "unused", "deprecation", "ConstantConditions", "ObsoleteSdkInt", "SpellCheckingInspection"}) @SuppressWarnings({"UnusedReturnValue", "WeakerAccess", "SameParameterValue", "unused", "deprecation", "ConstantConditions", "ObsoleteSdkInt", "SpellCheckingInspection"})
public class ShareUtil { public class ShareUtil {
@ -56,6 +71,10 @@ public class ShareUtil {
public final static SimpleDateFormat SDF_SHORT = new SimpleDateFormat("yyMMdd-HHmm", Locale.getDefault()); public final static SimpleDateFormat SDF_SHORT = new SimpleDateFormat("yyMMdd-HHmm", Locale.getDefault());
public final static String MIME_TEXT_PLAIN = "text/plain"; public final static String MIME_TEXT_PLAIN = "text/plain";
public final static int REQUEST_CAMERA_PICTURE = 50001;
public final static int REQUEST_PICK_PICTURE = 50002;
protected static String _lastCameraPictureFilepath;
protected Context _context; protected Context _context;
protected String _fileProviderAuthority; protected String _fileProviderAuthority;
@ -173,13 +192,45 @@ public class ShareUtil {
* @param file The file to share * @param file The file to share
* @param mimeType The files mime type * @param mimeType The files mime type
*/ */
public void shareStream(File file, String mimeType) { public boolean shareStream(File file, String mimeType) {
Uri fileUri = FileProvider.getUriForFile(_context, getFileProviderAuthority(), file);
Intent intent = new Intent(Intent.ACTION_SEND); Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath()); intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath());
intent.setType(mimeType); intent.setType(mimeType);
showChooser(intent, null);
try {
Uri fileUri = FileProvider.getUriForFile(_context, getFileProviderAuthority(), file);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
showChooser(intent, null);
return true;
} catch (Exception e) { // FileUriExposed(API24) / IllegalArgument
return false;
}
}
/**
* Start calendar application to add new event, with given details prefilled
*/
public void createCalendarAppointment(@Nullable String title, @Nullable String description, @Nullable String location, @Nullable Long... startAndEndTime) {
Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI);
if (title != null) {
intent.putExtra(CalendarContract.Events.TITLE, title);
}
if (description != null) {
description = description.length() > 800 ? description.substring(0, 800) : description;
intent.putExtra(CalendarContract.Events.DESCRIPTION, description);
}
if (location != null) {
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, location);
}
if (startAndEndTime != null) {
if (startAndEndTime.length > 0 && startAndEndTime[0] > 0) {
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startAndEndTime[0]);
}
if (startAndEndTime.length > 1 && startAndEndTime[1] > 0) {
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, startAndEndTime[1]);
}
}
_context.startActivity(intent);
} }
/** /**
@ -187,15 +238,29 @@ public class ShareUtil {
* *
* @param file The file to share * @param file The file to share
*/ */
public void viewFileInOtherApp(File file, @Nullable String type) { public boolean viewFileInOtherApp(File file, @Nullable String type) {
Uri fileUri = FileProvider.getUriForFile(_context, getFileProviderAuthority(), file); // On some specific devices the first won't work
Intent intent = new Intent(Intent.ACTION_VIEW); Uri fileUri = null;
intent.putExtra(Intent.EXTRA_STREAM, fileUri); try {
intent.setData(fileUri); fileUri = FileProvider.getUriForFile(_context, getFileProviderAuthority(), file);
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath()); } catch (Exception ignored) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try {
intent.setDataAndType(fileUri, type); fileUri = Uri.fromFile(file);
showChooser(intent, null); } catch (Exception ignored2) {
}
}
if (fileUri != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setData(fileUri);
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath());
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(fileUri, type);
showChooser(intent, null);
return true;
}
return false;
} }
/** /**
@ -473,4 +538,228 @@ public class ShareUtil {
} }
return null; return null;
} }
/**
* Request a picture from gallery
* Result will be available from {@link Activity#onActivityResult(int, int, Intent)}.
* It will return the path to the image if locally stored. If retrieved from e.g. a cloud
* service, the image will get copied to app-cache folder and it's path returned.
*/
public void requestGalleryPicture() {
if (!(_context instanceof Activity)) {
throw new RuntimeException("Error: ShareUtil.requestGalleryPicture needs an Activity Context.");
}
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
((Activity) _context).startActivityForResult(intent, REQUEST_PICK_PICTURE);
}
/**
* Request a picture from camera-like apps
* Result ({@link String}) will be available from {@link Activity#onActivityResult(int, int, Intent)}.
* It has set resultCode to {@link Activity#RESULT_OK} with same requestCode, if successfully
* The requested image savepath has to be stored at caller side (not contained in intent),
* it can be retrieved using {@link #extractResultFromActivityResult(int, int, Intent)},
* returns null if an error happened.
*
* @param target Path to file to write to, if folder the filename gets app_name + millis + random filename. If null DCIM folder is used.
*/
public String requestCameraPicture(File target) {
if (!(_context instanceof Activity)) {
throw new RuntimeException("Error: ShareUtil.requestCameraPicture needs an Activity Context.");
}
String cameraPictureFilepath = null;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(_context.getPackageManager()) != null) {
File photoFile;
try {
// Create an image file name
if (target != null && !target.isDirectory()) {
photoFile = target;
} else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", Locale.getDefault());
File storageDir = target != null ? target : new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
String imageFileName = ((new ContextUtils(_context).rstr("app_name")).replaceAll("[^a-zA-Z0-9\\.\\-]", "_") + "_").replace("__", "_") + sdf.format(new Date());
photoFile = new File(storageDir, imageFileName + ".jpg");
if (!photoFile.getParentFile().exists() && !photoFile.getParentFile().mkdirs()) {
photoFile = File.createTempFile(imageFileName + "_", ".jpg", storageDir);
}
}
//noinspection StatementWithEmptyBody
if (!photoFile.getParentFile().exists() && photoFile.getParentFile().mkdirs()) ;
// Save a file: path for use with ACTION_VIEW intents
cameraPictureFilepath = photoFile.getAbsolutePath();
} catch (IOException ex) {
return null;
}
// Continue only if the File was successfully created
if (photoFile != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri uri = FileProvider.getUriForFile(_context, getFileProviderAuthority(), photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
} else {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
}
((Activity) _context).startActivityForResult(takePictureIntent, REQUEST_CAMERA_PICTURE);
}
}
_lastCameraPictureFilepath = cameraPictureFilepath;
return cameraPictureFilepath;
}
/**
* Extract result data from {@link Activity#onActivityResult(int, int, Intent)}.
* Forward all arguments from activity. Only requestCodes from {@link ShareUtil} get analyzed.
* Also may forward results via local broadcast
*/
public Object extractResultFromActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CAMERA_PICTURE: {
String picturePath = (resultCode == RESULT_OK) ? _lastCameraPictureFilepath : null;
if (picturePath != null) {
sendLocalBroadcastWithStringExtra(REQUEST_CAMERA_PICTURE + "", EXTRA_FILEPATH, picturePath);
}
return picturePath;
}
case REQUEST_PICK_PICTURE: {
if (resultCode == RESULT_OK && data != null) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
String picturePath = null;
Cursor cursor = _context.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
for (String column : filePathColumn) {
int curColIndex = cursor.getColumnIndex(column);
if (curColIndex == -1) {
continue;
}
picturePath = cursor.getString(curColIndex);
if (!TextUtils.isEmpty(picturePath)) {
break;
}
}
cursor.close();
}
// Retrieve image from file descriptor / Cloud, e.g.: Google Drive, Picasa
if (picturePath == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
ParcelFileDescriptor parcelFileDescriptor = _context.getContentResolver().openFileDescriptor(selectedImage, "r");
if (parcelFileDescriptor != null) {
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
FileInputStream input = new FileInputStream(fileDescriptor);
// Create temporary file in cache directory
picturePath = File.createTempFile("image", "tmp", _context.getCacheDir()).getAbsolutePath();
FileUtils.writeFile(new File(picturePath), FileUtils.readCloseBinaryStream(input));
}
} catch (IOException ignored) {
// nothing we can do here, null value will be handled below
}
}
// Return path to picture on success, else null
if (picturePath != null) {
sendLocalBroadcastWithStringExtra(REQUEST_CAMERA_PICTURE + "", EXTRA_FILEPATH, picturePath);
}
return picturePath;
}
break;
}
}
return null;
}
/**
* Send a local broadcast (to receive within app), with given action and string-extra+value.
* This is a convenience method for quickly sending just one thing.
*/
public void sendLocalBroadcastWithStringExtra(String action, String extra, CharSequence value) {
Intent intent = new Intent(action);
intent.putExtra(extra, value);
LocalBroadcastManager.getInstance(_context).sendBroadcast(intent);
}
/**
* Receive broadcast results via a callback method
*
* @param callback Function to call with received {@link Intent}
* @param autoUnregister wether or not to automatically unregister receiver after first match
* @param filterActions All {@link IntentFilter} actions to filter for
* @return The created instance. Has to be unregistered on {@link Activity} lifecycle events.
*/
public BroadcastReceiver receiveResultFromLocalBroadcast(Callback.a2<Intent, BroadcastReceiver> callback, boolean autoUnregister, String... filterActions) {
IntentFilter intentFilter = new IntentFilter();
for (String filterAction : filterActions) {
intentFilter.addAction(filterAction);
}
final BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
if (autoUnregister) {
LocalBroadcastManager.getInstance(_context).unregisterReceiver(this);
}
try {
callback.callback(intent, this);
} catch (Exception ignored) {
}
}
}
};
LocalBroadcastManager.getInstance(_context).registerReceiver(br, intentFilter);
return br;
}
/**
* Request edit of image (by image editor/viewer - for example to crop image)
*
* @param file File that should be edited
*/
public void requestPictureEdit(File file) {
Uri uri = getUriByFileProviderAuthority(file);
int flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION;
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setDataAndType(uri, "image/*");
intent.addFlags(flags);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra(EXTRA_FILEPATH, file.getAbsolutePath());
for (ResolveInfo resolveInfo : _context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)) {
String packageName = resolveInfo.activityInfo.packageName;
_context.grantUriPermission(packageName, uri, flags);
}
_context.startActivity(Intent.createChooser(intent, null));
}
/**
* Get content://media/ Uri for given file, or null if not indexed
*
* @param file Target file
* @param mode 1 for picture, 2 for video, anything else for other
* @return
*/
public Uri getMediaUri(File file, int mode) {
Uri uri = MediaStore.Files.getContentUri("external");
uri = (mode != 0) ? (mode == 1 ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI : MediaStore.Video.Media.EXTERNAL_CONTENT_URI) : uri;
Cursor cursor = null;
try {
cursor = _context.getContentResolver().query(uri, new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "= ?", new String[]{file.getAbsolutePath()}, null);
if (cursor != null && cursor.moveToFirst()) {
int mediaid = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media._ID));
return Uri.withAppendedPath(uri, mediaid + "");
}
} catch (Exception ignored) {
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
} }

View file

@ -1,12 +1,11 @@
/*####################################################### /*#######################################################
* *
* Maintained by Gregor Santner, 2017- * Maintained by Gregor Santner, 2017-
* https://gsantner.net/ * https://gsantner.net/
* *
* License: Apache 2.0 / Commercial * License of this file: Apache 2.0 (Commercial upon request)
* https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0 *
*
#########################################################*/ #########################################################*/
import java.text.SimpleDateFormat import java.text.SimpleDateFormat