I'm launching a file explorer and doing some processing on the files from the explorer. I want the file explorer activity to close as soon as I hit the "Select" button. However, it seems as though it first does the processing in onFileQueueAvailable before closing.
private Queue<DocumentFile> fileQueue = new LinkedList<>();
static final int REQUEST_CHOOSE_FOLDER = 59;
public void startChooseFolder() {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(i, REQUEST_CHOOSE_FOLDER);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CHOOSE_FOLDER) {
fileQueue = new LinkedList<>();
Uri uri = data.getData();
DocumentFile chosenDirectory = DocumentFile.fromTreeUri(this, uri);
for (DocumentFile file : chosenDirectory.listFiles()) {
fileQueue.add(file);
}
}
}
#Override
protected void onResume() {
super.onResume();
if (!fileQueue.isEmpty()) {
onFileQueueAvailable(fileQueue);
}
}
The file explorer ends as soon as it calls finish. Its done. For you even to have onActivityResult called its already over. However onActivityResult is called before onResume and similar functions.
Related
Good day, all! I'm currently coding a plugin for Unity so that the user can access the file browser and pick an app. Upon picking the app, the file path is supposed to be saved. My code works so far, it's able to get the file path of the file but not the full one.
This is my code so far
int PICKFILE_RESULT_CODE = 1;
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/vnd.android.package-archive");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
}
#SuppressLint("InlinedApi")
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode==RESULT_OK && requestCode==PICKFILE_RESULT_CODE && data != null)
{
String apkPath = data.getData().getPath();
UnityPlayer.UnitySendMessage("Browser", "OnApkPick", apkPath);
Browser.this.finish();
super.onActivityResult(requestCode, resultCode, data);
}
}
Thanks in advance.
I'm trying to send an image path from one activity to another. I'm catching the intent in onResume, but the string path is always null. I don't know what I'm doing wrong. Hopefully you guys can help me with this problem.
Here's my activity where I grab the image path and send an intent.
private Intent testImage = new Intent(this, MyActivity.class);
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.card_create_layout);
testImage = new Intent(this, MyActivity.class);
}
private void grabImage()
{
Intent imageGetter = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(imageGetter, RESULT_LOAD_IMAGE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data)
{
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};//Array size of 1, and we put in a string
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
user_image_path = cursor.getString(columnIndex);//here we have our image path.
cursor.close();
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(BitmapFactory.decodeFile(user_image_path));
}
testImage.putExtra("the_image", user_image_path);
}
#Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.theCreateButton:
grabImage();
break;
case R.id.theDesButton:
startActivity(sendInformation);
}
}
#Override
public void onBackPressed()
{
super.onBackPressed();
MyActivity.checkCard();
setResult(Activity.RESULT_OK, getIntent());
finish();
}
Now in my other activity, when I grab the image and press back
#Override
public void onResume()
{
super.onResume();
String ImagePath = getIntent().getStringExtra("the_image");
if(ImagePath == null)
{
Toast.makeText(this,"hello everyone",Toast.LENGTH_LONG).show();
}
}
It keeps on showing the toast message "hello everyone", which means ImagePath is continuously null. How do I fix this?
Pass mechanism between activities is available in three ways :
via DI(Dependency Injection)
via Bundle mechanism
via Singletone class which play a role a bridge or data holder between activities.
To avoid duplicating answer - please search any way(i recommend easiest - via Bundle) in stackoverflow.
Quick guide :
You put your string into bundle via intent.putExtra(String name, String value) in Activity A
Start this intent with startActivity(intent);
In B activity read value view getIntent().getStringExtra(String name) in OnCreate method.
name value is need the same in activity A and B. This is a key.
I don't see a
startActivity(testImage);
If you aren't using that intent to start the activity, then there is no extra called 'the_image' and the getStringExtra function will effectively return a null.
#Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("the_image", user_image_path);
setResult(RESULT_OK, intent);
super.onBackPressed();
}
The above is how to correctly do it, if you have started an activity for result.
I am writing an android application. This app is built on top of Gmail. I want to add the ability to attach files from other apps. The first app I am working on doing this with is a custom Box app (made with the box sdk). I can currently send an intent, open an activity in the Box app, pick an attachment, and return. However, in my Box-SDK app, once an item is selected, I have no idea how to turn it into data that I can properly send back to my Gmail app (or any original sender of the intent). I also do not know how to send that data back to the originator of the intent.
I know setResult() is involved, but I am not sure where to put it or how to properly use it to carry the data chosen in box into the email app.
What's currently happening is it just goes back into gmail without an attachment and says that the download has finished.
Here is the code I currently have:
private void onFileSelected(final int resultCode, final Intent data) {
if (Activity.RESULT_OK != resultCode) {
Toast.makeText(this, "fail", Toast.LENGTH_LONG).show();
}
else {
final BoxAndroidFile file = data.getParcelableExtra(FilePickerActivity.EXTRA_BOX_ANDROID_FILE);
AsyncTask<Null, Integer, Null> task = new AsyncTask<Null, Integer, Null>() {
#Override
protected void onPostExecute(Null result) {
Toast.makeText(MainActivity.this, "done downloading", Toast.LENGTH_LONG).show();
// Intent result2 = new Intent();
// result2.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + ));
// setResult(Activity.RESULT_OK, result2);
//// setResult(resultCode, data);
super.onPostExecute(result);
finish();
}
#Override
protected void onPreExecute() {
Toast.makeText(MainActivity.this, "start downloading", Toast.LENGTH_LONG).show();
super.onPreExecute();
}
#Override
protected Null doInBackground(Null... params) {
BoxAndroidClient client = ((HelloWorldApplication) getApplication()).getClient();
try {
File f = new File(Environment.getExternalStorageDirectory(), file.getName());
Intent result2 = new Intent();
result2.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + f.getAbsolutePath()));
setResult(Activity.RESULT_OK, data);
// setResult(resultCode, data);
System.out.println(f.getAbsolutePath());
client.getFilesManager().downloadFile(file.getId(), f, null, null);
}
catch (Exception e) {
}
return null;
}
};
task.execute();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == AUTH_REQUEST) {
onAuthenticated(resultCode, data);
}
else if (requestCode == UPLOAD_REQUEST) {
onFolderSelected(resultCode, data);
}
else if (requestCode == DOWNLOAD_REQUEST) {
onFileSelected(resultCode, data);
}
}
Try using a file provider:
https://developer.android.com/reference/android/support/v4/content/FileProvider.html#ServeUri
From the page:
"There are a variety of ways to serve the content URI for a file to a client app. One common way is for the client app to start your app by calling startActivityResult(), which sends an Intent to your app to start an Activity in your app. In response, your app can immediately return a content URI to the client app or present a user interface that allows the user to pick a file. In the latter case, once the user picks the file your app can return its content URI. In both cases, your app returns the content URI in an Intent sent via setResult()"
From another stackoverflow answer:
public void showCameraScreen(View view) {
// BUILT IN CAMERA
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
camera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(this)) );
this.startActivityForResult(camera, 1);
}
private File getTempFile(Context context) {
// it will return /sdcard/MyImage.tmp
final File path = new File(Environment.getExternalStorageDirectory(), context.getPackageName());
if (!path.exists()) {
path.mkdir();
}
return new File(path, "MyImage.tmp");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == RESULT_OK) {
final File file = getTempFile(this);
byte[] _data = new byte[(int) file.length()];
try {
InputStream in = new FileInputStream(file);
in.read(_data);
in.close();
in = null;
//DO WHAT YOU WANT WITH _data. The byte array of your image.
} catch (Exception E) {
}
}
}
We can modify this code, where it says //Do What you want with the _data, just call
public final void setResult (int resultCode, Intent data)
This is the first time I post something here, so I apologize in advance for any mistake what-so-ever.
This is the situation:
I'm currently developing my first android app, sort of like a tracker:
1. log in
2. select weather, temperature etc
3. press the start button that activates a background GPS service and shows you a list of other attendees
4. click on an attendee and it shows you a timeline where you can add pictures etc.
Here is where the fun starts. When I open the camera it works most of the time, but once in a while the activity that opens the camera gets destroyed and when reopening (to further progress) it opens a second camera.
When I take a picture like that it completely ignores the first picture, restarts the gps-service, messes up my timeline and shows the login dialog when I go back to the the main activity (which is programmed to only show up when starting the app).
I have read an similar topic and it might be the solution, but I can't get it to work.
The code for the camera activity:
public class AddPhotoActivity extends Activity {
private SharedPreferences savedValues;
private String mCurrentPhotoPath;
private String imageName;
private int id;
private String startRideDateTime;
private SimpleDateFormat dateInSQL = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private Date date;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_photo);
savedValues = this.getSharedPreferences("SavedValues",
Context.MODE_PRIVATE);
id = savedValues.getInt("RideId", 0);
startRideDateTime = savedValues.getString("StartRideDateTime", "");
try {
date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(startRideDateTime);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat dateInDir
= new SimpleDateFormat("yyyyMMdd_HHmmss");
startRideDateTime = dateInDir.format(date);
if (savedInstanceState == null) {
dispatchTakePictureIntent();
}
}
#Override
protected void onResume() {
super.onResume();
savedValues = this.getSharedPreferences("SavedValues",
Context.MODE_PRIVATE);
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
ex.printStackTrace();
}
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, 1);
}
}
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp;
File sdCard = Environment.getExternalStorageDirectory();
File storageDir = new File(sdCard.getAbsolutePath() + „/app/„ + id + "/" + startRideDateTime + "/photos");
storageDir.mkdirs();
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
imageName = image.getName();
return image;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (mCurrentPhotoPath != null) {
addPhotoToDb();
mCurrentPhotoPath = null;
}
} else if (resultCode == RESULT_CANCELED) {
finish();
}
}
private void addPhotoToDb() {
TimeLineDataSource timeLineDataSource = new TimeLineDataSource(this);
timeLineDataSource.open();
date = new Date();
String dateString = dateInSQL.format(date);
timeLineDataSource.createTimeLineItem(3, imageName, dateString);
timeLineDataSource.close();
finish();
}
public void onBackPressed() {
finish();
}
}
If anybody knows a solution to this I would be eternally grateful!
Update:
although I had better code after the previous suggestion it still didn't solve the problem. It seems that devices with less memory can get terminated at DVM-level, causing them to quit without onDestroy(). My issue is more or less resolved, but includes a lot of patchwork that I feel can be done in other, more efficient ways.
The code below is what I usually use for taking a photo/picking a photo. I normally include the ability to pick a previous photo or take a new photo, and I don't run into this issue.
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);
//zero can be replced with any action code to pick photo from gallery
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);
//one can be replced with any action code
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode) {
case 0:
if(resultCode == RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
imageview.setImageURI(selectedImage);
}
break;
case 1:
if(resultCode == RESULT_OK){
Uri selectedImage = imageReturnedIntent.getData();
imageview.setImageURI(selectedImage);
}
break;
}
}
Also, I agree with the solution from the other post, this in particular:
In the case of a destroyed activity, when the activity result needs to
be processed, Android will recreate the Activity, passing a
savedInstanceState to onCreate. So, the remedy is to check the value
of savedInstanceState in your GetImageActivity.onCreate. If it is not
null then don't make any calls to startActivity because your Activity
is being recreated to call onActivityResult.
Optionally, if you need to preserve any state then override
onSaveInstanceState(Bundle outState) and put data you need into
outState.
It even can't make a folder on the sdcard. When the camera takes the photo, it doesn't respond when I press the 'OK' Button. What's wrong with my code?
public static final String MACCHA_PATH = Environment.getExternalStorageDirectory().getPath() + "/Twigit";
public static final String PHOTO_PATH = MACCHA_PATH + "/camera.jpg";
public static boolean takePhoto(Activity activity) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File fileDir = new File(MACCHA_PATH);
boolean isSuccessful = true;
if (!fileDir.exists()) {
isSuccessful = fileDir.mkdir();
}
if(!isSuccessful) {
return false;
} else {
File file = new File(PHOTO_PATH);
Uri outputFileUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
activity.startActivityForResult(intent, TAKEPHOTO);
return true;
}
}
do you have this? You need to override the onActivityResult. which will be called before onResume when you use startActivityForResult. The requestCode will be the code you used to start the photo taking activity. In your case it would be TAKEPHOTO..
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKEPHOTO) {
if (resultCode == RESULT_OK) {
//Pic taken
} else {
//Pic not taken
}
}
}
EDIT:
take a look at this link
http://achorniy.wordpress.com/2010/04/26/howto-launch-android-camera-using-intents/