I have a (big) problem on chromebook with a functionnality working fine on "classic" android devices (phones, tablets).
I try to send an e-mail with an attached file.
Here's a portion of code (api>=23).
Intent email = new Intent(Intent.ACTION_SEND);
String[] str = new String[1];
str[0] = "destination#yahoo.fr";
email.putExtra(Intent.EXTRA_EMAIL, str);
email.putExtra(Intent.EXTRA_TEXT, "My text");
email.putExtra(Intent.EXTRA_SUBJECT, "My subject");
Uri uri = FileProvider.getUriForFile(this, "com.TTT.fileprovider", new File(dest));
email.putExtra(android.content.Intent.EXTRA_STREAM, uri);
email.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
email.setType("message/rfc822");
startActivity(email);
On my Phone (android 9 api 28), gmail app is called, all text fields are filled with correct information and the file (myResume.pdf) is correctly attached.
When sent then received, the e-mail contains a readable pdf file. that's cool.
With my chromebook (PB 314 / v. 83.0.4103.119), gmail is called, all text fields are filled with correct information but no attached file.
LogCat indicates :
2020-06-27 15:25:50.886 127-2348/? I/ActivityManager: START u0 {act=android.intent.action.SEND typ=message/rfc822 flg=0x43 cmp=org.chromium.arc.applauncher/.ChromeBrowserProxyActivity clip={message/rfc822 T:My text} (has extras)} from uid 10040
2020-06-27 15:25:50.887 565-565/? D/ArcDummy: New intent received: Intent { act=android.intent.action.SEND typ=message/rfc822 flg=0x10000043 cmp=org.chromium.arc.applauncher/.ChromeBrowserProxyActivity clip={message/rfc822 T:My text} (has extras) }
2020-06-27 15:25:50.887 565-565/? W/ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.startService:1531 android.content.ContextWrapper.startService:664 org.chromium.arc.applauncher.DummyActivity.forwardIntentIfNeeded:155 org.chromium.arc.applauncher.DummyActivity.onNewIntent:121 android.app.Activity.performNewIntent:7255
2020-06-27 15:25:50.892 127-2348/? W/WindowManagerInjector: Attempted to get menu state of app token with non existing window
2020-06-27 15:25:50.896 780-842/? D/ArcMediaControllerManager: onTaskMovedToFront: 2
2020-06-27 15:25:50.897 780-842/? I/ArcMediaControllerManager: onAppBecameActive: org.chromium.arc.applauncher
2020-06-27 15:25:50.892 127-2348/? W/WindowManagerInjector: Attempted to get menu state of app token with non existing window
2020-06-27 15:25:50.900 127-760/? W/ActivityManager: For security reasons, the system cannot issue a Uri permission grant to content://com.TTT.fileprovider/images/myResume.pdf [user 0]; use startActivityAsCaller() instead
2020-06-27 15:25:50.901 127-760/? W/WindowManagerInjector: Attempted to get menu state of app token with non existing window
when testing on android phones, this sentence never appears :
For security reasons, the system cannot issue a Uri permission grant to content://com.TTT.fileprovider/images/myResume.pdf [user 0]; use startActivityAsCaller() instead
more information about previous code :
the file "myResume.pdf" is copied to a special directory for beeing shared with gmail.
dest is a string (/storage/emulated/0/MyDir/myResume.pdf) obtained with
Environment.getExternalStorageDirectory().toString() > /storage/emulated/0/
my sub directory, created and verified > MyDir/
the file > myResume.pdf
the file AndroidManifest.xml includes
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.TTT.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
the file #xml/provider_paths is :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="images" path="myDir/"/>
</paths>
I hope I have explained my problem with all details,
Can anyone help me?
Thank you very much!
the problem is finally solved by using gmail app (after downloaded it) then using it instead of gmail/web/chrome.
Related
Need to utilise the camera in my app for work, I see that things have changed in API >= 28 compared to how I used to do it where I could use startActivityForResult.
However I am facing a problem where I launch the camera app, and immediately get the 'TransactionTooLargeException' error message in the debug/run console.
For calling up the camera, I am doing
mGetContent = registerForActivityResult(
new ActivityResultContracts.TakePicture(),
result -> {
if (result) {
}
}
);
Where mGetContent is defined in the class as
private ActivityResultLauncher<Uri> mGetContent;
In my AndroidManifest.xml file I have the following
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.test.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
In my file_paths file I have
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path
name="files"
path="."/>
<files-path
name="app_images"
path="./files/"/>
</paths>
I have a button set up in my activity where I launch the camera using
findViewById(R.id.button)).setOnClickListener(v -> {
File directory = new File(context.getFilesDir(), "app_images");
if (!directory.exists()) directory.mkdir();
File file = new File(directory, "image.jpg");
Uri uri = getUriForFile(this, "com.test.fileprovider", file);
mGetContent.launch(uri);
};
As soon as I tap on the button, and the camera app opens up, I get what I can only assume is an overly general error message.
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 1284092)
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test, PID: 14296
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 1284092 bytes
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Caused by: android.os.TransactionTooLargeException: data parcel size 1284092 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:511)
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4524)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
Been trying to Google search to find things, but having trouble nailing down what the actual issue is.
Some suggestions pointed me towards the onSaveInstanceState, so I override that and set a breakpoint on it to see what was happening, but it made it through without any issues (from what I could tell).
Kind of at a loss with this one.
Wowsers as to what makes up the bundle in the onSaveInstanceState.
I have some imageviews, imagebuttons, and just general buttons in my app to make things easier for our staff.
I went through and changed the 'saveState' of all the ImageViews and ImageButtons from the default of true to false, since I don't care what state they were in, they are just visual guides.
Took the android:viewHierarchyState from 1.2MB down to 1.6KB, my Parcel size is now 3.3KB and it no longer crashes when suspending the app to bring up the camera app.
TooLargeTool was useful, but I couldn't make it work the way the Github page says, I told it to 'startLogging', and in my activity where the crash was happening, I set a breakpoint and checked if it was logging using 'isLogging' and it came back 'true'.
In the end I just had it log the output of TooLargeTool.bundleBreakdown(outState) in the onSaveInstanceState.
Thanks to Gabe Sechan and ianhanniballake for pointing me towards what it might be, there's not much out there on for this particular exception, I mean, there is, but it appears that it is different for everyone.
Really wish Google would print out a better set of error messages for it to make it easier to work out which activity was the problem (or in my case, all 3 activities combined).
I'm working with Android Studio, writing in Java. I'm trying to write a piece of software that will take pictures from a camera based on an event. So first steps first was to figure out the API. Camera is depreciated, so there's Camera2, but the latest is CameraX. I've attempted to use both CameraX and Camera2, but for some reason I'm not saving any images. I believe the capture works, but the issue is saving the files. I don't know what's going on.
First lets start with permissions. Yes, I have set permissions for both the camera and external storage.
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
So lets move on to the code itself.
I've never saved photos before, but I have worked with text files such as .txt and .csv files. Which I've been able to make work.
Right now I do a simple button click to capture the image. Which is nothing more than an onclicklistener. Once I press the button this is what actions occur.
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(Environment.getDataDirectory(), mDateFormat.format(new Date())+ ".jpg");
if(!file.exists())
file.mkdirs();
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
imageCapture.takePicture(outputFileOptions, executor, new ImageCapture.OnImageSavedCallback () {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "TEST", Toast.LENGTH_SHORT).show();
new Handler().post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Image Saved successfully", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onError(#NonNull ImageCaptureException error) {
error.printStackTrace();
// Toast.makeText(MainActivity.this, "Image save FAILED!!!!", Toast.LENGTH_SHORT).show();
}
});
when the app launches the first time, it asks for permission and I grant permission. but looking at the run tab as part of the Android Studio ID, I get the following readout, when I press the capture button
D/ImageCapture: Send image capture request [current, pending] = [0, 1]
D/CaptureSession: Issuing capture request.
W/example.camera: JNI critical lock held for 21.148ms on Thread[14,tid=10076,Runnable,Thread*=0xdc743000,peer=0x13184cf8,"Binder:10045_2"]
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
Skip the tag entry since data format (ULONG) is unexpected for tag: GPSAltitudeRef
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
Stop reading file since a wrong offset may cause an infinite loop: 0
W/System.err: androidx.camera.core.ImageCaptureException: Failed to write or close the file
W/System.err: at androidx.camera.core.ImageCapture$3.onError(ImageCapture.java:669)
at androidx.camera.core.ImageSaver.lambda$postError$1$ImageSaver(ImageSaver.java:263)
at androidx.camera.core.-$$Lambda$ImageSaver$eAp-cZyzsEk-LVLazzLE-ezQzwo.run(Unknown Source:8)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.io.FileNotFoundException: /data/20200728142756.jpg: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
at androidx.camera.core.ImageSaver.run(ImageSaver.java:97)
... 3 more
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
at libcore.io.IoBridge.open(IoBridge.java:482)
... 6 more
W/example.camera: JNI critical lock held for 17.651ms on Thread[16,tid=10083,Runnable,Thread*=0xdc74bc00,peer=0x13184de8,"Binder:10045_4"]
I've searched around, and looked for different methods of saving the file, and I've had success with saving the image, sort of, when I use the camera2 api and save the file using outputstream
When I use Camera2 it appears to save just fine, but I have no idea where it saves, I can't find it. I point this out, because it still appears to be a permission denied error as what I'm seeing is when I open up Device File Explorer its not letting me view /storage/emulator/ it just shows me
ls: /storage/emulated/: Permission denied.
all the examples I have found have assumed access with no issues to emulated.
Does anyone have any insight as to why I'm having permission denied errors?
UPDATE
So I still haven't solved the issue related to the failed mkdir() call. However, I did fix one issue, that could have been causing the issue. The means as to how I was creating the directory and the file itself wasn't correct.
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(getBatchDirectoryName(), mDateFormat.format(new Date())+ ".jpg");
public String getBatchDirectoryName() {
String app_folder_path = "";
app_folder_path = Environment.getExternalStorageDirectory() + "/images";
File dir = new File(app_folder_path);
if (!dir.exists() && !dir.mkdirs()) {
Toast.makeText(MainActivity.this, "Trip", Toast.LENGTH_SHORT).show();
}
return app_folder_path;
}
However, it still fails to create the directory. Which still makes me come back to a permission issue.
Environment.getExternalStorageDirectory() appears to be deprecated. Documentation appears to recommend using getExternalFilesDir(string) or MediaStore. However, I'm having issues finding sample use cases. And I can't imagine, that while deprecated, it would just stop working at all. Most devices on the market are not API 29 or higher.
Based on help from #blackapps, I was able to make changes to my Manifest file to allow access to external storage.
More information can be found here
Request Legacy External Storage
With #blackapps, and this thread on stackoverflow I was able to update my permissions to allow legacy access.
Because in Android Q they have disabled direct file access, they have added a work around to allow legacy support. This is, and as others have mentioned, only a temporary fix for the issue. You will need to follow the new format for saving files going forward with Android R. In my situation, I am only developing a proof of concept and will not need to worry about future versions of Android.
To make the temporary fix, do the following
Add the following line
android:requestLegacyExternalStorage="true">
inside your <application bracket on the manifest file. Should look similar to this
<?xml version="1.0" encoding="utf-8"?>
...
package="com.example.camerax">
...
<application
...
android:requestLegacyExternalStorage="true">
<activity android:name=".MainActivity">
<intent-filter>
...
</intent-filter>
</activity>
</application>
remember this is not a long term fix, and will not work when a device is updated to Android R
I'm following the File transfer example on the Nearby Connections Exchange page (the "more complex example" code snippet).
I can send an image and receive it on another device in the Download/Nearby folder. The image is sent successfully since if I were to change the file name to give it an appropriate extension (e.g. .jpg), I can open the image in a photo gallery app.
private void processFilePayload(long payloadId) {
Payload filePayload = completedFilePayloads.get(payloadId);
String filename = filePayloadFilenames.get(payloadId);
if (filePayload != null && filename != null) {
completedFilePayloads.remove(payloadId);
filePayloadFilenames.remove(payloadId);
// Retrieve received file from Downloads folder
Payload.File payloadFile2 = filePayload.asFile();
File payloadJavaFile = payloadFile2.asJavaFile();
if (payloadJavaFile == null) {
Log.d(TAG, "Payload java file is null in processFilePayload()");
} else {
payloadJavaFile.renameTo(new File(payloadJavaFile.getParentFile(), filename));
}
}
}
Why is the payloadJavaFile variable null? From looking at Payload.class, I know that the result of asJavaFile() is a nullable File and that, from the asJavaFile() method description, calling asJavaFile() in processFilePayload() from within onPayloadReceived() (as is done in the example on the API page) may lead to the File not having received all of the payload's contents yet. However, I also call processFilePayload() from within onPayloadTransferUpdate() after verifying the success of the PayloadTransferUpdate, and so shouldn't the payload have received all of its contents by this stage (and not be null when calling asJavaFile() on the payload object)?
My code is almost the same as the documentation for both sending and receiving the image and file name.
Payload.asJavaFile() will be null if the READ_EXTERNAL_STORAGE permission is not properly set up for your application. You need READ_EXTERNAL_STORAGE in the AndroidManifest.xml and you need to also request READ_EXTERNAL_STORAGE permission at runtime since it is a dangerous permission. (https://developer.android.com/training/permissions/requesting)
To share files using Nearby Connections, your application will need all of the following:
AndroidManifest.xml
<!-- Required for Nearby Connections -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Optional: needed to share files -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
MainActivity.java
ActivityCompat.requestPermissions(thisActivity,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
},
PERMISSIONS_REQUEST_CODE);
We will improve the documentation to make this requirement for sharing files more obvious.
I checked the source code. From what I can see, asJavaFile() is always set (and I'm not sure why it's marked as #Nullable).
Unfortunately, for me to look into it any further, I'd need you to provide me with a sample app that reproduces the bug you're seeing.
I have an app that, due to lack of mobile data in all areas, uses phone connection to make a phone call. There is some important information on the screen in my app, so I want to place the call without leaving my app screen. Is there any way to do this?
Add the following permission in mainfest file
<uses-permission android:name="android.permission.CALL_PHONE" />
Use the below code to start calling
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "123456789" ));
startActivity(intent);
If you want to implement inside tha app read the tutorial which will help you alot
I am trying to write a service that runs on phone boot, and must read data off the SD card. At first I was using a reciever for android.intent.action.BOOT_COMPLETED but switched to the intent below to make sure that the SD card has been loaded.
My Issue is that on a my Nexus 7, it doesn't appear to receive the MEDIA_MOUNTED intent. The Nexus 7 doesn't have an SD card (but it has separate SD card partition). I also tried the BOOT_COMPLETED intent, with the same luck. I have tested the same code on the emulator and my Thunderbolt, and both intents work.
Manifiest:
<receiver
android:name=".StartupReceiver"
android:enabled="true"
android:exported="true"
android:label="Start the NFS Automounter Service">
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED"></action>
<data android:scheme="file"/>
<!-- <action android:name="android.intent.action.BOOT_COMPLETED"></action>-->
</intent-filter>
</receiver>
The BroadcastReceiver class:
public class StartupReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction()))
//if ("android.intent.action.MEDIA_MOUNTED".equals(intent.getAction()))
//{
Log.d("NFS_Automounter", "Recieved Mount");
Intent serviceIntent = new Intent("com.ancantus.nfsautomounter.AutomountService");
context.startService(serviceIntent);
//}
}
}
I commented out the intent matching just to try and log if the class is executed at all.
My only hunch is that the Nexus 7 doesn't broadcast a MEDIA_MOUNTED because it doesn't have a real SD card; but I can't receive the BOOT_COMPLETED intent either.
And to forstall the question; yes I do have the BOOT_COMPLETED permission.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
How many times must I type in this answer before it starts coming up in enough search results that people will find it? Maybe boldface caps will work:
STARTING WITH ANDROID 3.1, NO BroadcastReceiver WILL WORK, AT ALL, UNTIL SOMETHING HAS MANUALLY RUN ONE OF THE APPLICATION'S OTHER COMPONENTS, SUCH AS A USER RUNNING AN ACTIVITY.
This is in the documentation (albeit not well located), in blog posts, and in many StackOverflow answers, such as:
https://stackoverflow.com/a/9084771/115145
https://stackoverflow.com/a/11865858/115145
https://stackoverflow.com/a/11744499/115145
So, add an activity to your app. You need some activities anyway, for settings to control your background operation, for your documentation, for your license agreement, for your privacy policy, etc.
(note: I'm not really yelling at you -- I am just frustrated that this keeps coming up despite efforts to get the word out...)
Please note that many Android devices emulate SD card in the way it does not affect access to the SD card even when desktop accesses it. Therefore it may be that Nexus 7 simply exposes all memory that way, so as it does not really mount anything, it'd not broadcast MEDIA_MOUNTED. If you want to do some tasks on boot, listening to BOOT_COMPLETED is the only correct approach.