I am developing an app which enables the user to select a file and do processing on it after getting the path of it, I have written a code which gets me the path like this
private void OpenFile()
{
Intent i = new Intent(Intent.ActionGetContent);
i.SetType("application/zip");
StartActivityForResult(i,0);
}
In activity for result I am extracting the path as follows:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 0)
{
if (resultCode == Result.Ok)
{
string uri = data.DataString;
System.Uri myUri = new System.Uri(uri, System.UriKind.Absolute);
Android.Net.Uri uris = Android.Net.Uri.FromParts(data.Scheme, myUri.LocalPath, myUri.Fragment);
// string a= myUri.LocalPath;
System.IO.Stream input= ContentResolver.OpenInputStream(uris);
string uri = data.DataString;
ZipLogic.Unzip(uri);
}
}
}
And the results are in such pattern:
content://com.android.externalstorage.documents/document/xxxx-83BB%3xxx%2Fxxx.zip
But this path when I try to access from returns DirectoryNotFound Exception
I am unable to resolve how to open this path as a Stream.
Luckily, I found the answer by watching closely the Intent data.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
if (requestCode == 0)
{
if (resultCode == Result.Ok)
{
string uri = data.DataString;
//intent variable has a Field named Data which is the complete URI for the file.
Android.Net.Uri uris = Android.Net.Uri.FromParts(intent.Data.Scheme, intent.Data.SchemeSpecificPart, intent.Data.Fragment);
System.IO.Stream input = ContentResolver.OpenInputStream(intent.Data);
//related tasks
}
}
}
Explanation:
The selected file result has a field named Data in the Intent object, that is basically the Uri Invoker which tends to be a URI object
I used it to get an input stream from ContentResolver.
Related
I have a Firebase Recycler View which contains a button like this
final String post_key = getRef(position).getKey();
viewHolder.btnUpload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent data = new Intent();
data.putExtra("post_key",post_key);
Log.d("post_key", data.getExtras().getString("post_key"));
data.setType("image/*");
data.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(data, GALLERY_REQUEST);
}
});
This will trigger an action in OnActivityResult(). I was trying to access the variable "post_key" in OnActivityResult. Therefore, I put it to the extra, and call the getString function in OnActivityResult.
final String post_key=data.getExtras().getString("post_key");
However, the app crashed and keeps telling me that I attempt to invoke virtual method 'getString' on a null object reference
You need to check the request code and the result code as well:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GALLERY_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
// here you can access the intent
String msg = (data != null) ? data.getStringExtra("post_key") : "";
Log.d("post_key", "Got post_key: " + msg);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
You can not send your data to another app - if it does not accept. The thing you are doing is not mentioned anywhere.
Correct Way
in onClick don't pass extra, and hold your post_key in your activity/ adapter.
adapter.setPostKey(post_key);
Then in onActivityResult() get this post_key.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GALLERY_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
String post_key = adapter.getPostKey();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
I know with Android 7 you can't pass File// but in this case I'm not doing that. For testing purposes, when a user selects a file, I just want to intent to another class. When I click a video, the app just stops responding so there isn't a crash log or anything. This is my onActivityResult method:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_TAKE_GALLERY_VIDEO) {
Uri selectedImageUri = data.getData();
// OI FILE Manager
String filemanagerstring = selectedImageUri.getPath();
// MEDIA GALLERY
String selectedImagePath = getPath(selectedImageUri);
if (selectedImagePath != null) {
Log.d(TAG, "THE PATHHHHHHHHH " + selectedImagePath);
Intent intent = new Intent(getActivity().getApplicationContext(),
GalleryUpload.class);
// intent.putExtra("path", selectedImagePath);
startActivity(intent);
}
}
}
}
Replace all of that with:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_TAKE_GALLERY_VIDEO) {
Uri selectedImageUri = data.getData();
Intent intent=new Intent(getActivity(), GalleryUpload.class)
.setData(selectedImageUri)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
}
}
}
This correctly handles both file and content Uri schemes, including passing along read access to GalleryUpload.
GalleryUpload can then use getIntent().getData() to retrieve the Uri, then use ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri.
I am wondering if using a Chooser means you can't send extra custom data to the receiving intent?
I call a file selection intent like this
public static void receiveFiles(final AppCompatActivity activity, int which) {
Intent receiveIntent = new Intent(Intent.ACTION_GET_CONTENT);
receiveIntent.setType("text/comma-separated-values");
String[] mimetypes = {"text/csv", "text/comma-separated-values", "application/csv"};
receiveIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
receiveIntent.addCategory(Intent.CATEGORY_OPENABLE);
receiveIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
receiveIntent.putExtra(IMPORT_OPTION_WHICH, which); //this line
activity.startActivityForResult(Intent.createChooser(receiveIntent, "Pick CSV"), REQUEST_IMPORT_CSV);
}
But then in onActivityResult after the user selects a file:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_IMPORT_CSV:
if (data != null) {
Uri uri = data.getData(); //is correct
int which = data.getIntExtra(IMPORT_OPTION_WHICH, -1);
//but this always -1!
}
break;
}
}
}
How can I get it to correctly extract the value I passed into the intent?
I'm switching from using the default camera to finally growing a pair and deciding to make a custom camera. It's only showing me how much I don't fully understand.
Here is basically way I have been doing things in the main activity as far as photos go, but it will no longer work:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == PICK_PHOTO_REQUEST) {
if (data == null) {
Toast.makeText(this, "General Error!", Toast.LENGTH_LONG).show();
}
else {
mMediaUri = data.getData();
}
Log.i(TAG, "Media URI: " + mMediaUri);
}
else {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(mMediaUri);
sendBroadcast(mediaScanIntent);
}
(...)
Here is the picture saving function along with a couple others of the new camera:
(...)
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.d("Picture taken");
String path = savePictureToFileSystem(data);
setResult(path);
finish();
}
private static String savePictureToFileSystem(byte[] data) {
File file = getOutputMediaFile();
saveToFile(data, file);
return file.getAbsolutePath();
}
private void setResult(String path) {
Intent intent = new Intent();
intent.putExtra(EXTRA_IMAGE_PATH, path);
setResult(RESULT_OK, intent);
}
*Credit to Paul Blundell
(...)
What do I need to do so that the main activity can receive the image's URI in the onactivityresult instead of the path String? Are URIs even applicable when it comes to custom cameras?
Please and thanks.
You use custom camera, but want to do it via Intent? OK, you have the absolute file path in
String abspath = data.getExtras().getString(EXTRA_IMAGE_PATH);
mMediaUri = Uri.fromFile(new File(abspath));
I read an text input from the user, this input i use it as a name of a picture i'm taking by the camera.
i store this name and the path of the image name into Sqlite Database.
what I'm trying to do is, after clicking OK to accept the taken picture, i want the saved path to be displayed in a toast.
the problem is, when I click OK to accept the picture, nothing is being displayed and i cant switch from the camera activity to the activity that called the camera activity"the previous activity"
Note: I'm using the emulator not a real device.
OnClickListener btn_TakePictureListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String imgPath = retrievePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri(imgPath));
startActivityForResult(intent, RequestCode);
}
};
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RequestCode && resultCode == RESULT_OK) {
String s = data.getData().toString();
Toast.makeText(getBaseContext(), ""+s, Toast.LENGTH_SHORT).show();
}
}
if you are passing Uri for you image then you can retrieve image as taken by camera:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
Environment.getExternalStorageDirectory(), "temp.jpg")));
startActivityForResult(intent, 1);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == NONE)
return;
if (requestCode == 1) {
// Set the file save path with directory
File picture = new File(Environment.getExternalStorageDirectory()
+ "/temp.jpg");
Uri imageuri= Uri.fromFile(picture);
//set to imageview here
}
}
EDIT:
For Getting data uri in onActivityResult start Camra Activiyt as:
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_UNSPECIFIED);
startActivityForResult(intent, 2);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == NONE)
return;
if (requestCode == 1) {
Uri uriimg = data.getData();
Toast.makeText(getBaseContext(), ""+uriimg.toString(), Toast.LENGTH_SHORT).show();
}
}