Drawable.createFromPath(path) returns null, imgView.setImageURI returns null, image added manually and called programmatically - java

Im trying to do the next:
Find image from device and add it to programm (done!)
Store image URI to string and save it to .txt file (done!)
Extract URI from .txt file (done!)
Open a dialog window to show the image on click - and there is a problem - i've tryied everything i found on google and stack overflow - both methods does not work - drawable returns no image (drawable = null), and setImageURI crashes the application.
Debugger shows something like that:
content://com.android.providers.media.documents/document/image%3A31
code:
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.pop_up_add_item, null);
final Button btn=view.findViewById(R.id.test);
imgg=view.findViewById(R.id.img);
String str_tooltip=getArguments().getString("Entity");
String main_str=getArguments().getString("Original");
String str_adress=getArguments().getString("Uri");
Uri uri = Uri.parse(str_adress);
//imgg.setI(uri);
if (str_adress!=null & str_adress.length()>0) {
final Uri uri1 = Uri.parse(str_adress);
//final String path = uri.getPath();
//File drawableFile = new File(getApplicationContext().getFilesDir().getAbsolutePath()+"/into11.png");
//final Drawable drawable = Drawable.createFromPath(path);
imgg.setImageURI(uri);
}
Is there any solution on this? Probably common problem?
UPDATE
After tried all the available options eventually (thanks to sir #Dilshad) i've found that the trouble is caused by java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{1a24ed9 11931:com.example.myapplication/u0a121} (pid=11931, uid=10121) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs --> Permission issue.
So, trying to solve it i added:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
in AndroidManifest
and
int result = ContextCompat.checkSelfPermission(takeThis, android.Manifest.permission.READ_EXTERNAL_STORAGE);
in the place in the code where the access begins.
But till the moment problem is not solved.

Related

Display photo from FileProvider with Intent.ACTION_VIEW

I am working on a device running Android 8.1.0. I'm trying to open an image from a message attachment. I had a cache of image files working using a FileProvider a week ago and now it just stopped working without me touching the code. I'm trying to share an image from my internal app storage to Intent.ACTION_VIEW outside of my app. The photo viewer does launch, but there's a progress circle that just keeps spinning. Any suggestions? Thanks!
void launchViewer(File f) {
Uri uri = FileProvider.getUriForFile(context, "com.company.secure.provider", f);
Intent intent = new Intent(Intent.ACTION_VIEW);
String mimeType = Attachment.getMimeType(f.getName());
//TODO Test to make sure this works on all devices...
if (mimeType.startsWith("video")) {
mimeType = "video/*";
}
if (mimeType.startsWith("image")) {
mimeType = "image/*";
}
if(mimeType==null || mimeType.length()==0) {
unknownMimeType(f.getName());
return;
}
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if(resInfoList==null || resInfoList.size()==0)
{
AlertDialog dialog = new AlertDialog.Builder(context).setTitle("Error")
.setMessage(String.format("Cannot find app to open file type(%s)",mimeType)).show();
return;
}
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setDataAndType(uri, mimeType);
context.startActivity(intent);
}
So I just had to add the following line right before starting the activity.
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
For some reason, the APK I shipped to testing that doesn't have this line in it works... but any new build does not work without this. I read that using the ResolveInfo method will only work for Lollipop and below and you will have to grant the permission directly to the intent. (Not sure how true this is). For this reason I left both permission granting methods in there to cover all bases. Thanks for all the help!

Image not being shared to Apps

I want my users to be able to share an image and select an app to share it to whether its something like their native messenger app, or twitter. Whenever I go to select the app I want to share the image to, I get a message saying "This media can't be loaded" or something like that. Here is the sharing code in BitmapUtils.java
static void shareImage(Context context, String imagePath) {
// Create the share intent and start the share activity
File imageFile = new File(imagePath);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri photoURI = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, imageFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
context.startActivity(shareIntent);
}
Here is my file provider code in my Manifest file:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.aaronapp.hideme.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
Here is the file_paths file which contains the file paths.
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-cache-path name="my_cache" path="." />
<external-path name="my_images" path="Pictures/" />
</paths>
Here is the share method that is invoked inside the MainActivity class.
/**
* OnClick method for the share button, saves and shares the new bitmap.
*/
#OnClick(R.id.share_button)
public void shareMe() {
// Delete the temporary image file
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
// Share the image
BitmapUtils.shareImage(this, mTempPhotoPath);
}
If you need anymore information that I forgot to show I'll be happy to supply it. I'm trying to fix this issue and get my images to share to different apps(I know Facebook has a certain way of sharing images, but I will tackle that later)
You can also replicate this issue by downloading the Hide me, Emoji App on the google play store, taking a picture and trying to share it across your apps.https://play.google.com/store/apps/details?id=com.aaronapp.hideme
This will allow you to read files from Internal or external sdcard.
Add this in manifest.xml
<!-- this is For Access External file Storage -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.demo.test.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
<root-path
name="external_files"
path="/storage/"/>
</paths>
Try with adding flag Intent.FLAG_GRANT_READ_URI_PERMISSION to Intent
The file you want to share with another app, you need to allow the client app to access the file. To allow access, grant permissions to the client app by adding the content URI to an Intent and then setting permission flags on the Intent.
// Grant temporary read permission to the content URI
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
The permissions you grant are temporary and expire automatically when the receiving app's task stack is finished.
Please try this code, this is working in my case
File filePath = new File(FIlePath);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
ArrayList<Uri> uriArrayList = new ArrayList<>();
uriArrayList.add(getUriFromFilePath(filePath));
intent.setType("image/*");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriArrayList);
startActivity(intent);
public Uri getUriFromFilePath(Context theCtx, File theSrcPath) {
Uri requirdUri = null;
// observation
// SDKversion: 25 -- Uri.fromFile Not working, So we have to use Provider
// FileProvider.getUriForFile will not work when the file is located in external Sdcard.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
requirdUri = FileProvider.getUriForFile(theCtx,
theCtx.getApplicationContext().getPackageName() + PROVIDER_FILE_EXTENSION,
theSrcPath);
} else {
requirdUri = Uri.fromFile(theSrcPath);
}
return requirdUri;
}
I have done following changes in your code, i had tested app after
changes and able to share image now.
Please check and let me know.
in MainActivity, shareMe method you have delete the temp file before sharing that why the error was occured.
now i have delete the Temp file after sharing.
Modified code in MainActivity.java
public static final int REQUEST_CODE_SHARE_FILE = 100;
public void shareMe()
{
// BitmapUtils.deleteImageFile(this, mTempPhotoPath); delete temp file in on activity result.
BitmapUtils.shareImage(MainActivity.this, mTempPhotoPath);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
//If the image capture activity was called and was successful
if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK)
{
processAndSetImage();
}
else if(requestCode == REQUEST_CODE_SHARE_FILE)
{
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
}else {
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
}
}
Modified code in BitmapUtils.java
static void shareImage(Activity activity, String imagePath) {
// Create the share intent and start the share activity
File imageFile = new File(imagePath);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri photoURI = FileProvider.getUriForFile(activity, FILE_PROVIDER_AUTHORITY, imageFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
activity.startActivityForResult(shareIntent,MainActivity.REQUEST_CODE_SHARE_FILE);
}
I am testing your app on the device with Android version 6.0 and app gets crashed every time.
Inside detectFacesandOverlayEmoji method, on line number 32(SparseArray faces = detector.detect(frame);)
a) Sometimes app remains open without showing anything in logcat.
b) Sometimes app crashed with following error in logcat.
05-24 11:00:27.192 17880-17880/com.aaronapp.hideme E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aaronapp.hideme, PID: 17880
java.lang.OutOfMemoryError: Failed to allocate a 51916812 byte allocation with 16765168 free bytes and 36MB until OOM
at com.google.android.gms.vision.Frame.zzTM(Unknown Source)
at com.google.android.gms.vision.Frame.getGrayscaleImageData(Unknown Source)
at com.google.android.gms.vision.face.FaceDetector.detect(Unknown Source)
at com.aaronapp.hideme.HideMe.detectFacesandOverlayEmoji(HideMe.java:32)
at com.aaronapp.hideme.MainActivity.processAndSetImage(MainActivity.java:153)
at com.aaronapp.hideme.MainActivity.onActivityResult(MainActivity.java:133)
at android.app.Activity.dispatchActivityResult(Activity.java:6428)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Make use of Picasso, sharing you a working code from my project.
Put this in your App level gradle,
implementation 'com.squareup.picasso:picasso:2.71828'
Code used is given below,
static void shareImage(Context context, String imagePath) {
// Create the share intent and start the share activity
Picasso.with(getApplicationContext())
.load(imagePath)
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("image/*");
i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(bitmap));
if (!TextUtils.isEmpty(des)) {
i.putExtra(Intent.EXTRA_TEXT, des);
}
startActivity(Intent.createChooser(i, "Share Image"));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}
public Uri getLocalBitmapUri(Bitmap bmp) {
Uri bmpUri = null;
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
"share_image_" + System.currentTimeMillis() + ".png");
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
Hope it may help you.

Download instead of load url in WebView when url contains x

I have an Android app that is pretty much a WebView containing a mobile website. I have minimum control over the code of the website but can inject javascript.
The website contains download links to PDF, DOC, ZIP etc. files, with most of them only accessible if the user is logged in. At first I simply made the app open links containing "FileHandler.axd" (the script that handles files) in the normal browser, but if users are not logged in through the app ánd browser they'll just get an error.
So now I'm trying to make the app use the download manager if a link is tapped but am having some trouble as it's not really working at all. I don't have a lot of experience developing Android apps so any lead on where I'm doing it wrong would be greatly appreciated.
These are my permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I marked the code I added last with a "DOWNLOAD MANAGER CODE BELOW" comment block.
This is part of my MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
if(CheckNetwork.isInternetAvailable(MainActivity.this)) {
// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
// Get current UserAgent
String curua = mWebView.getSettings().getUserAgentString();
// Add -comapp string to useragent for detection
mWebView.getSettings().setUserAgentString(curua + "-comapp");
// Use remote resource
mWebView.loadUrl("https://www.onsplatform.tv/comapp");
// Stop local links and redirects from opening in browser instead of WebView
mWebView.setWebViewClient(new MyAppWebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
//hide loading image
findViewById(R.id.imageLoading1).setVisibility(View.GONE);
}
});
/////////////////////////////////
// DOWNLOAD MANAGER CODE BELOW //
/////////////////////////////////
if(mWebView.getUrl().contains("FileHandler.axd")){
String url = mWebView.getUrl();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "download");
// You can change the name of the downloads, by changing "download" to everything you want, such as the mWebview title...
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
}
} else {
//no connection
Toast toast = Toast.makeText(MainActivity.this, "geen internet / no internet", Toast.LENGTH_LONG);
toast.show();
}
}
Edit
I'm getting a feeling I put the code in the wrong place. I'm guessing I need a public method for the WebViewClient? But which one, onLoadResource()? I've been reading the documentation but I don't really know if I'm looking at the right stuff.
I'm guessing there's a sort of event handler that fires when a link is loading, maybe being able to intercept that, start the download manager for that url and prevent the url from loading in the webview?
I have a class that extends WebViewClient, I'm guessing that would be the place:
public class MyAppWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().endsWith("onsplatform.tv")) { // && !url.toLowerCase().contains("filehandler")) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
}

Get Texture from google play game services Icon Uri in Libgdx

I am trying to show user profile icon in my game in libgdx. In the android side of code, i can get the image uri for the player using mParticipants.get(i).getIconImageUri() which gives me the Uri. But I can't find a way to convert the Uri to Texture which i can consume in my libgdx code.
I tried first getting the bitmap from Uri using the code
Bitmap bitmap = null;
try {
InputStream inputStream = application.getContentResolver().openInputStream(imgUri);
bitmap = BitmapFactory.decodeStream(inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
But this gives me a security error.
Other answers on google shows me the ways, all of which include the ways to show image in an Android ImageView but i need a texture which i can use in my libgdx game to show the image
I have also tried adding following permission to my manifest
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Even then i am still getting security error. Please help me to resolve this issue
After a lot of research it seemed to me that it is Not Possible to get the bitmap by reading the input stream for the Uri. The only way to do this is using the ImageManager
The sample code for achieving this is:
private void SetUserIconForPlayer(final Player player, Uri uri)
{
ImageManager mgr = ImageManager.create(application);
mgr.loadImage(new ImageManager.OnImageLoadedListener() {
#Override
public void onImageLoaded(Uri uri,final Drawable drawable, boolean isRequestedDrawable) {
if(isRequestedDrawable)
{
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
player.SetUserIcon(GetTextureFromDrawable(drawable));
}
});
}
}
}, uri);
}

Android No Activity found - STILL_IMAGE_CAMERA

I am getting the following exception in my android app.
No Activity found to handle Intent { act=android.media.action.STILL_IMAGE_CAMERA (has extras) }
I know that my device, an MC70, has a camera.
bool hasFeature = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
int numCameras = android.hardware.Camera.getNumberOfCameras();
Both hasFeature is true and numCameras > 0
The device has an SD card installed:
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
In the AndroidManifest.xml file I have:
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
final PackageManager packageManager = context.getPackageManager();
This list comes back empty, probably a bad sign:
final Intent intent = new Intent(action);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
This code must run on the MC70, which is limited to KitKat 4 API 19.
But when I call:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 1);
I get the exception:
No Activity found to handle Intent { act=android.media.action.STILL_IMAGE_CAMERA_SECURE (has extras) }
I have tried:
MediaStore.ACTION_IMAGE_CAPTURE
MediaStore.ACTION_IMAGE_CAPTURE_SECURE
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
All throw the exception. Why?
Why?
Because the device manufacturer did not install a camera app that supports any of those Intent structures. If the device does not legitimately ship with the Play Store on it, there is no requirement that the manufacturer have to meet any particular compatibility requirements.
Assuming that you do not need a camera app with any particular features, install an open source one, like Open Camera, so your device has an app that responds to ACTION_IMAGE_CAPTURE, etc.

Categories

Resources