I am trying to get image's Uri in the Gallery built-in app from inside my application.
so, I was using the Intent below, but it selected many more image.
i want to set limitation. less than 3
#Override
public void onClick(View v) {
Intent intent = new Intent( );
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(Intent.createChooser(intent, "select images"), PICK_IMAGE_MULTIPLE);
}
how do i fix this.
Do you have any suggestions?
Unfortunately, as stated by http://developer.android.com/reference/android/content/Intent.html#EXTRA_ALLOW_MULTIPLE, this is not possible.
This is a boolean extra; the default is false. If true, an implementation is allowed to present the user with a UI where they can pick multiple items that are all returned to the caller.
You'll have to manually check the returned data to see if it's more than 3 items, and if so, show a Toast and let them try again.
As Daniel stated, there is no possibility with Intent.EXTRA_ALLOW_MULTIPLE. An alternative though, is using the MultipleImageSelect library. Not only can you select multiple images, but the extra ability to set a limit on images selected by the user.
Check out the repository or a sample.
STEPS:
Step 1:
Add MultipleImageSelect library, together with jitpack.io to your build.gradle like this:
repositories {
maven {
url "https://jitpack.io"
}
}
dependencies {
implementation 'com.github.darsh2:MultipleImageSelect:v0.0.4'
}
Step 2:
In project's AndroidManifest.xml, add the following under application node:
<activity
android:name="com.darsh.multipleimageselect.activities.AlbumSelectActivity"
android:theme="#style/MultipleImageSelectTheme">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Step 3:
In the activity from where you want to call image selector, create Intent as follows:
mSelectImagesBtn.setOnClickListener(view -> {
Intent intent = new Intent(ListingImages.this, AlbumSelectActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_LIMIT, 3); //set desired image limit here
startActivityForResult(intent, Constants.REQUEST_CODE);
});
Step 4:
and override onActivityResult like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.REQUEST_CODE && resultCode == RESULT_OK && data !=null) {
ArrayList<Image> images =data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES);
imagePathList.clear();
StringBuffer stringBuffer = new StringBuffer();
//loop to retrieve the paths of each image and display to TextView
for (int i = 0; i < images.size(); i++) {
stringBuffer.append(images.get(i).path + "\n");
}
textView.setText(stringBuffer.toString());
}
}
DONE
Alternatively,
If you're using an Adapter to inflate images to display, you can instead have this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.REQUEST_CODE && resultCode == RESULT_OK && data != null) {
ArrayList<Image> images = data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES);
imagePathList.clear();
for (int i = 0; i < images.size(); i++) {
imagePathList.add(images.get(i).path);
}
imageAdapter.notifyDataSetChanged();
}
}
Within ImageAdapter, display images to populate recyclerView, like follows:
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
String path = imagePathList.get(position);
Picasso.with(mContext)
.load(new File(path))
.placeholder(R.drawable.ic_house_placeholder)
.into(holder.image);
}
Related
These codes can only capture and display image I took, and when I pressed save button, it only saves "Note title" onto my list View. And when I clicked "Note Title" it doesn't display the picture anymore. What should I add to save it and update it? Thanks.
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap mphoto = (Bitmap) data.getExtras().get("data");
imageviewid.setImageBitmap(mphoto);
}
}
public void takeImageFromCamera(View view) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
private void saveNote(){
fillNameIfEmpty();
id = DbAccess.addNote(getBaseContext(), etName.getText().toString(), mFileName, DbContract.NoteEntry.TYPE_PHOTO, currentCat);
Toast.makeText(getApplicationContext(), R.string.toast_saved, Toast.LENGTH_SHORT).show();
}
private void updateNote(){
fillNameIfEmpty();
DbAccess.updateNote(getBaseContext(), id, etName.getText().toString(), mFileName, currentCat);
Toast.makeText(getApplicationContext(), R.string.toast_updated, Toast.LENGTH_SHORT).show();
}
Your DbAccess API doesn't know anything about an image in the note!
So I would extend your code to:
After picture is taken it saved in fail in application sandbox
Save filename of image assigned to note to database together with note
And don't forget to handle editing or deletion picture use cases!
When im trying to delete a show with an AsyncTask. I want to call finish() after the AsyncTask has been completed and return an Intent with the result.
from the activity:
new DeleteShowTask().execute();
Intent intent = new Intent(SeasonActivity.this, FragmentShows.class); // I'm not sure if this works
intent.putExtra("tvdbid", tvdbId);
setResult(DELETECODE, intent);
finish();
then in the fragment i have this:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("RESULTCODE", resultCode + "");
Log.d("REQUEST CODE", requestCode +"");
if (resultCode == SeasonActivity.DELETECODE)
{
if (requestCode == SeasonActivity.SHOW)
{
String tvdbid = data.getStringExtra("tvdbid");
for (int i = 0; i < adapter.getCount(); i++) {
SickbeardSerie serie = adapter.getItem(i);
if (serie.getTvdbId().equals(tvdbid))
{
adapter.remove(serie);
adapter.notifyDataSetChanged();
}
}
}
}
}
But it seems like it doenst run through this onAcitivityResult().
I have logged the onActivityResult() as you see but i dont get any logs.
Only thing i get is: 10-19 16:21:44.631: W/FragmentActivity(27672): Activity result fragment index out of range: 0x2fffe
I fixed it for now by using a work around.
I now reload my AsyncTask in the onResume() instead of just removing an item from the arraylist and calling adapter.notifyDataSetChanged(). But its not the best solution.
if you using a Fragment in a another Fragment. You should be call
getParentFragment().startActivityForResult(i, SELECT_PICTURE);
I am making a activity whereby i ask the user to load image from various sources and showing the selected image on a imageview in a different activity.
I am able to show the image from the camera and gallery but from dropbox it is showing error.
For Camera and gallery i can even query the uri obtained from
intent.getData()
in the onactivityresult method and obtain the Filepath and accordingly even obtain the bitmap and resize it .
But the same is not working for Dropbox. Kindly update what code to use for Dropbox so that all options start working.
thanks
For Dropbox you will need to use their Android Chooser to choose files from the user's Dropbox account. You will need a Dropbox API key for this. Once you have grabbed the chooser library and your API key it should be fairly easy to implement;
private Button mChooserButton;
private DbxChooser mChooser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChooser = new DbxChooser(APP_KEY);
mChooserButton = (Button) findViewById(R.id.chooser_button);
mChooserButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mChooser.forResultType(DbxChooser.ResultType.PREVIEW_LINK)
.launch(MainActivity.this, DBX_CHOOSER_REQUEST);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DBX_CHOOSER_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
DbxChooser.Result result = new DbxChooser.Result(data);
Log.d("main", "Link to selected file: " + result.getLink());
// Handle the result
} else {
// Failed or was cancelled by the user.
}
} else if (requestCode == GALLERY) {
// If your request was from the user gallery
Log.d("main", "Link to selected file: " + data.getData());
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
I call camera to take a picture. But I cannot go back to my own original activity after taking the picture. What's the problem? Thank you.
public void addEntry(View view)
{
String EntryName=RegisterName.toString();
Toast.makeText(this, EntryName, Toast.LENGTH_LONG);
Intent addEntryintent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(getFilesDir(),EntryName);
registeryFileUri = Uri.fromFile(file);
addEntryintent.putExtra(MediaStore.EXTRA_OUTPUT, registeryFileUri);
startActivityForResult(addEntryintent,TAKE_PICTURE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE)
{
if (data != null)
{
Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
Registerimage.setImageURI(registeryFileUri);
}
}
}
It took me a while to get it working and I have made several things and finally it works. I can't tell certainly which of the things I did is the solution to the problem, but they all together form the working solution.
There are multiple reasons why the camera activity does not return back. Two major ones are:
path for the new picture is invalid, or non-existing, or it can't be created
application got suspended and saved path get lost.
So here is my code solving all these problems, all together working.
First I created helper class ImageServices:
class ImageServices {
private static String getTempDirectoryPath(Context ctx) {
File cache;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = ctx.getCacheDir();
}
// Create the cache directory if it doesn't exist
if (!cache.exists()) {
cache.mkdirs();
}
return cache.getAbsolutePath();
}
public static Uri getOutputImageFileUri(Context ctx) {
// TODO: check the presence of SDCard
String tstamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = new File(getTempDirectoryPath(ctx), "IMG_" + tstamp + ".jpg");
return Uri.fromFile(file);
}
}
The code is partially inspired by developer.android.com and partially by CameraLauncher class of Apache Cordova project.
In my activity the event handler for button to take a picture looks like this:
private Uri imageFileUri;
private static final int MAKE_PHOTO_RESULT_CODE = 100;
private static final int PICK_PHOTO_RESULT_CODE = 101;
public void onMakePhoto(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageFileUri = ImageServices.getOutputImageFileUri(this);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
Log.i("babies", "Taking picture: requested " + imageFileUri);
startActivityForResult(intent, MAKE_PHOTO_RESULT_CODE);
}
Method onActivityResult does not really contain much, as imageFileUri already points to the existing file and necessary rendering is done in onResume method, which is called when the activity gets back into foreground:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch(requestCode) {
case MAKE_PHOTO_RESULT_CODE:
assert imageFileUri != null;
break;
case ...
...other cases...
break;
}
}
}
But this is still not sufficient, as imageFileUri gets lost as your app gets suspended. And on regular device the chances are close to 100%. So next you need to store the value of imageFileUri to instance state:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (imageFileUri == null) {
outState.putString("file-uri", "");
}
else {
outState.putString("file-uri", imageFileUri.toString());
}
};
and load it again in - easiest is directly in onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
String fileUri = savedInstanceState.getString("file-uri");
if (!fileUri.equals("")) imageFileUri = Uri.parse(fileUri);
}
}
So, again, on top of many other solutions presented on this site as well as elsewhere, there are two major differences:
smarter getTempDirectoryPath inspired by Apache Cordova
allowing imageFileUri to survive suspended application
And now - at least for me - everything works fine.
Answer
Use appContext.getExternalCacheDir() and don't forget to mention permissons.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE)
{
if(resultCode==Activity.RESULT_OK)
{ //if (data != null)
//{
Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
Registerimage.setImageURI(registeryFileUri);
//}
}
else
Toast.makeText(this, "Not Registered!", Toast.LENGTH_LONG);
}
**"android.permission.CAMERA"**
Check whether the above permission is specified in your manifest or not
Note: It's better to use getExternalCacheDir() than getFilesDir() if you still dont get the
image then use that. Dont forgot to specify the permission "android.permission.WRITE_EXTERNAL_STORAGE" if you use the getExternalCacheDir().
On some devices data will unfortunately be null in onActivityResult after calling the camera activity. So you may need to save your state in your activity's variables, and them read them in onActivityResult. Be sure to save these variables in onSaveInstanceState and restore them in onCreate.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
deserializeQuotes();
quotesAdapter.notifyDataSetChanged();
}
}
My array clearly has been updated, and I can see the change when my app starts, but why doesn't it update in this method? The code enters this method.
this.quotesAdapter = new QuoteAdapter(this, R.layout.mainrow, quotes);
quotesAdapter.notifyDataSetChanged();
listView.setAdapter(quotesAdapter);
Works, but why do I have to create a new adapter? Why can't I use my existing one?