Access image URI from adapter - java

I have a main activity, in which the user is shown a dialogue to pick an image from the gallery or use the camera. The problem is ( I think ) that i'm building against the 6.0 APIs and the permissions are what's messing me up.
When the application passes the Uri (As a string) into a database, the Adapter has to access that database and get the picture and put it into an ImageView.
I get the READ_EXTERNAL_STORAGE permission to access the file in the MainActivity, but I think I also need it in the adapter, but I can't access permissions from in there.
//TL;DR how can I access the internal storage (pictures) from inside of a recyclerview adapter class?
Here's my code:
After I check for permissions, I start the intent to pick the image:
//RESULT_LOAD_IMAGE = 0;
Intent toGal = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(toGal, RESULT_LOAD_IMAGE);
then, inside of the onActivityResult, I get the URI and set a variable to it's string value
boolean request = requestCode == RESULT_LOAD_CAMER || requestCode == RESULT_LOAD_IMAGE;
if (resultCode == Activity.RESULT_OK && request && imageReturnedIntent != null) {
Uri selectedImage = imageReturnedIntent.getData();
picturePath = String.valueOf(selectedImage);
Log.i(TAG, picturePath);
}
And then I store it in a Realm database, and access it from the adapter. I know this is not the problem, because I can log the path that was stored in the db that points to the image just fine.
Here is where I access it inside of the Adapter:
String imgString = Model.getImage(); //This is "/emulated/storage/pathtoimg.jpg"
if (imgString != null) {
Bitmap BM = BitmapFactory.decodeFile(imgString);
ImageView.setImageBitmap(BM);
}
}
But nothing happens. When I try to request permissions from inside the Adapter it says it needs to be an activity so how can I access the internal storage from a recyclerview adapter?

Related

Alternative for onActivityResult

So i am making app in Android studio(java) and i am using image picker from https://github.com/Dhaval2404/ImagePicker. Is there a way to get result from image picker without using deprecated method
onActivitiyResult() ? I have read https://www.tutorialguruji.com/android/onactivityresult-method-is-deprecated-what-is-the-alternative/ this article but i am not quite sure how to use image picker in this context.
Thanks for any kind of help!
First of all you have to create a Uri (a path from where you want User to select the image), then you can use this Uri to pass to the intent and it will directly go to that Uri. Here, due to Storage Access Changes on Android 10 onwards we can't directly get the path to root directory, so here we pass the uri to get all the images present in External Volume of Device. And in Android 9 below we can directly access Root Directory, so the Uri is different.
binding.imageCamera.setOnClickListener { v ->
Uri uri;
if (isSdk29andUp()){
uri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
Intent intent = new Intent(Intent.ACTION_PICK, uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pickPhotoLauncher.launch(intent);
}
ActivityResultLauncher<Intent> pickPhotoLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
// Here the data will be Uri.
}
}
});
}

Capturing image from camera and setting it to image view [duplicate]

One feature of my app includes the camera. The user takes a picture and the app displays the image.
I start an intent with ACTION_IMAGE_CAPTURE using StartActivityForResult and capture the response with onActivityResult. Usually I can simply call getData() on the intent I receive in onActivityResult and get the content uri for the MediaProvider.
My problem is the following: One one of my test devices, a Huawei ALE-L21, the intent I get in onActivityResult has no data, but instead, it has a parcellable extra. How could I get the users photo from that? Android Studio doesn't tell me the name of the parcellable extra either
Disclaimer: I call getActivity() because I'm using this code in a fragment
This is what I use to get the camera.
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, getResources().getInteger(R.integer.RQ_PERMISSION_WRITE_EXTERNAL_STORAGE));
}
And here's the code in my onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent resultIntent) {
super.onActivityResult(requestCode, resultCode, resultIntent);
switch (requestCode) {
case 1: //RQ_ImageCapture
case 2: //RQ_ImageSelected
if (resultIntent != null) {
try {
Uri selectedImage = resultIntent.getData();
if(selectedImage != null) {
Bitmap bitmap =
MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), selectedImage);
setImageAsBackground(selectedImage, bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
}
break;
}
}
Usually I can simply call getData() on the intent I receive in onActivityResult and get the content uri for the MediaProvider.
Your code will fail on many of them, including all recent Nexus devices. ACTION_IMAGE_CAPTURE is not supposed to return a Uri. Quoting the documentation:
If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field. This is useful for applications that only need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri value of EXTRA_OUTPUT.
Since you are not including EXTRA_OUTPUT, you will get a data extra (getData().getExtra("data")) with a thumbnail image.
the intent I get in onActivityResult has no data, but instead, it has a parcellable extra
Given your ACTION_IMAGE_CAPTURE request, that is what you are supposed to get.
If you want a full-size image, include EXTRA_OUTPUT, perhaps pointing to a FileProvider in your app, such as I demonstrate in this sample app. Then, you know the Uri where the photo should go, because you specified that Uri.

Android app dev: trying to save an image to store into SQLite

I am creating an Android app for class that will take you to the camera app if you click the "capture" button on my user interface. It then returns you to the app and displays the images thumbnail and if you click the "save" button, it will save the button in a SQLite database that I haven't created yet.
My problem is trying to figure out how to access the actual picture and its data, not information about the thumbnail.
The tutorial I was reading has information for storing the image in Android's built in Android's directories, but I can not figure out how to access the actual fullsize image data to store into the database I will be creating myself.
This is the link to the tutorial:
https://developer.android.com/training/camera/photobasics#java
This is not the complete code, just a snipet and it was created in Android Studio:
'''
ImageView pic;
public void capture(View view) {
dispatchTakePictureIntent();
}
public void save(View view) {
}
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
pic.setImageBitmap(imageBitmap); // sets the imageview on the UI as the thumbnail
}
}
'''
I believe that you need to pass a URI of a storage location (file), via the takePictureIntent intent using
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, your_image_Uri);
You can then open the file and retrieve it into a byte[] and store it as a blob. The SQLiteDatase convenience, insert method makes this very easy.
e.g. assuming the byte[] is name my_picture then
ContentValues cv = new ContentValues();
cv.put(column_name_for_picture,my_picture);
long id = insert("the_table_name",null,cv);
You retrieve the stored picture from the db using the SQLiteDatabase query method and then extract the byte[] using the Cursor's getBlob method.
However
If the picture, is 2MB or larger, you will not be able to retrieve it as there is a limitation of 2MB for a CursorWindow (1MB for older versions of Android). I'd suggest that even at 1MB you may well have issues retrieving the image(s).
The recommended way is to not store the image in the database, but to store the path of a file where the image is stored in the database.
You may wish to have a look at How to use images in Android SQLite that are larger than the limitations of a CursorWindow? as this shows a work-around albeit NOT recommended.

Keep a static variable throughout taking a picture and coming back

On my on create function I give the location an ID. However my issue is when I go to add a photo to that page before I've saved it. I need to save the photo with the same ID as the page. So I create the ID on the on create then when i add a picture and come back as it's loaded the other intent it runs the code again and creates a new ID. How can I pass the ID through the photo and back.
The variable checkStationObjectID is set at the top of the file.
Heres my on create:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_asset);
Bundle extras = getIntent().getExtras();
Log.e("CamDebug", "Loading extras");
if (extras != null) {
PreviousStationObjectID = extras.getString("StationObjectID");
editMode = extras.getBoolean("editMode");
editAreaObjectID = extras.getString("editAreaObjectID");
}
if(editMode){
checkStationObjectID = editAreaObjectID;
Log.e("CHECK ID - Edit mode", checkStationObjectID);
} else {
if(checkStationObjectID == null){
checkStationObjectID = NewAssetStationObjectID;
Log.e("CHECK ID = NEW ID", checkStationObjectID);
}
}
//Other items taken out
}
I launch the camera with:
public void startCamera()
{
File photo = null;
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
photo = new File(Global.Pictures + timestamp +".png");
}
else
{
photo = new File(getCacheDir(), FOLDER_NAME+File.separator+timestamp+".png");
}
if (photo != null)
{
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
selectedImageUri = Uri.fromFile(photo);
startActivityForResult(intent, CAPTURE_IMAGE_CALLBACK);
}
}
onCreate is called whenever your application is started. If you are calling another app like a camera, then the OS can kill your own Activity at any time while the camera Activity is running. This could be to recover memory or resources that the running app needs. Then when you exit the camera the OS will restart your Activity, which will call onCreate again.
I would suggest that you save the ID that you have generated into SharedPreferences just before you start the camera app. Then check for a saved ID in onActivityResult.
If you don't need to persist it you can create a Singleton object to act as a session and store the variable in there.. But I don't get why onCreate is executed again.. I thought the sub camera activity should return in onActivityResult? I pardon me if I misunderstood.
Or you can pass the var to the camera activity and pass it back when you are done with it.

Using the camera activity in Android

If you want to use the built-in camera activity which uses the native Android camera, simply do the following.
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
this.startActivityForResult(camera, PICTURE_RESULT);
You want to get the images back from the nifty camera you displayed -- but how?
If you want to get the image back in its full glory, pass in a uri to the Intent within the EXTRA_OUTPUT extra. If you're fine with a smallish bitmap (and you should be), just call the intent as normal.
Now you have two options, deal with the uri of the image that is returned in the EXTRA_OUTPUT extra, or do the following in your onActivityResult method:
if (requestCode == PICTURE_RESULT) //
if (resultCode == Activity.RESULT_OK) {
// Display image received on the view
Bundle b = data.getExtras(); // Kept as a Bundle to check for other things in my actual code
Bitmap pic = (Bitmap) b.get("data");
if (pic != null) { // Display your image in an ImageView in your layout (if you want to test it)
pictureHolder = (ImageView) this.findViewById(R.id.IMAGE);
pictureHolder.setImageBitmap(pic);
pictureHolder.invalidate();
}
}
else if (resultCode == Activity.RESULT_CANCELED) {...}
}
And there you go!

Categories