onActivityResult never called from widget launched activity - android

I'm new here. I discover how StackOverflow works.
I'm creating a new android homescreen widget. My widget has a button. When pressed, it starts an activity (it's not a configure Activity, just a standard activity). In this activity, I have a test button. My purpose is to create a text file after pressing this test button.
In onCreate function, I have this code to handle the button :
final Button testButton = findViewById(R.id.button_test);
test.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(WidgetActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
Utils.MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
String fileName = "test.txt";
Intent exportIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
exportIntent.addCategory(Intent.CATEGORY_OPENABLE);
exportIntent.setType("text/plain");
exportIntent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(exportIntent, FILE_EXPORT_REQUEST_CODE);
}
});
And I have this function :
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK)
return;
switch (requestCode) {
case FILE_EXPORT_REQUEST_CODE:
if (data != null) {
Uri uri = data.getData();
if (uri != null) {
Context c = WidgetActivity.this;
ParcelFileDescriptor pfd = null;
try {
pfd = c.getContentResolver().openFileDescriptor(uri, "w");
Preferences.export(mAppWidgetId, pfd.getFileDescriptor(), WidgetActivity.this);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
break;
}
}
onActivityResult is never called.
I put this code in my MainActivity, and it works very well.
I don't know how to achieve this...

It's seems to be impossible.
The way I achieve this :
My widget starts its activity (not the MainActivity), as usual, and one feature offer the possibility to create a file.
The button in this activity create a new intent with action code, and launch MainActivity.
MainActivity use action code to decide what to do : execute code to create the file.
MainActivity have a onActivityResult called when user choose a file name and a directory.

Related

How do I go back to previous screen on pressing back button in Android

When Clicked on a button on screen, Camera will be opened. I saw few posts on stack overflow regarding this question. I tried finish(), finishActivity(), onBackPressed() methods after dispatchTakePictureIntent(); in onClick method but then failed! It exits my entire app.
This are the excerpts from my full code:
Button's onClick method:
mCaptureImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("TAG", "Camera opened");
dispatchTakePictureIntent();
}
});
This method dispatches Intent:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
"com.pc.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
My Question is, How do I go back to the previous screen when the back
button is pressed when I'm on Camera's Intent.
Thus you have to do Nothing :
you cant override methods in external activities you are calling.
However, when a user hits back in an activity that was called using
startActivityForResult the response code RESULT_CANCELLED is generally
returned (there may be instances where this isn't true). In your
onActivityResult method simply check for the RESULT_CANCELLED code and
call whatever functionality you need
Could you try using startActivityForResult and check if your onActivityResult gets called or on back press Activity's onResume gets called

Finish Activity not close in Android (Xamarin)

I have Two Activity one is InventoryActivity and Second is StoneDetailActivity. In my InventoryActivity have RecycleView In RecycleView Button Click I start the StoneDetailActivity using StartActivityForResult below code.
Intent stonedetailIntent = new Intent(context, typeof(StoneDetailActivity));
stonedetailIntent.PutExtra("SearchitemObject", stoneJson);
stonedetailIntent.PutExtra("position", position);
context.StartActivityForResult(stonedetailIntent, 1000);
context.OverridePendingTransition(Resource.Animation.Slide_in_right, Resource.Animation.Fade_back);
In StoneDetailActivity Button click I use this code to Finish the current Activity and go to OnBackPressed().
public override void OnBackPressed()
{
Intent intent = new Intent();
intent.PutExtra("BoolCheck", postflag);
intent.PutExtra("Position", position);
SetResult(Result.Ok, intent);
Finish();
}
and In InventoryActivity I have set this code.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == Result.Ok)
{
bool checkflag = data.GetBooleanExtra("BoolCheck", false);
int position = data.GetIntExtra("Position", -1);
if (checkflag && position > -1)
{
searchItems.RemoveAt(position);
inventAdapter.NotifyDataSetChanged();
txt_totalStone.Text = searchItems.Count.ToString();
txt_totalCarat.Text = searchItems.Sum(c => c.Weight.Value).ToString();
txt_totalAmount.Text = searchItems.Sum(c => c.Rate.Value).ToString();
mainActivityBool = true;
badgeCounttextView.Text = BizApplication.BADGE_COUNT.ToString();
}
}
}
Button Click code :
add_to_cart_button.Click += async (sender, e) =>
{
ProgressDialog pdialog = new ProgressDialog(this);
pdialog.SetMessage("Please Wait...");
pdialog.Show();
cartItem = new CartItem();
cartItem.StoneId = searchItem.PacketId;
cartItem.UserId = BizApplication.getCredential().Id;
cartItem.Amount = searchItem.Rate.Value;
cartItem.Discount = searchItem.Discount;
postflag = await InventoryService.AddToCart(cartItem);
if (postflag)
{
OnBackPressed();
BizApplication.BADGE_COUNT += 1;
}
pdialog.Dismiss();
};
this code work fine for first Time. But Again if I do the same process, the StoneDetailActivity set open eventhough if I click finish.
UpDate :
When I full debug my code and i found that when I click on Second time OnBackPressed(). and Finish it my debug again start the OnCreate activity that's why it happening. But I am not starting Again then Why is Happening.
What happen I don't understand. Any Help be Appreciated.
As per this Post the Problem was that inside ListView or RecycleView if we are perform some task like OnclickListener then we have check is OnclickListener like below way other it will fire multiple event.
if (!button.HasOnClickListeners)
{
button.Click += this.clickHandler;
}
Then the code is working fine.
For more detail visit this :
https://forums.xamarin.com/discussion/9244/single-click-on-button-invoking-multiple-clicks
try by adding flag Intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);

How to pass through a separate parameter through the Camera intent in android

I'm creating a dynamic form activity and I get the instructions on how to make the forms from a db. The activity essentially just scrolls the list of questions and sees what type they are and adds them. So it's an activity that adds a view as a question. That all works fine by itself. I tried to keep the responses/questions inside the specific question classes which just subclass a base question.
The problem I'm having is when I try to add a camera "question" to prompt the user to take a picture, I can't get the result inside the view. I managed the launch the activity in the view, and it returns the result to the questionnaire activity. The activity doesn't know which question it's meant to add it to, since it's all done dynamically. So I tried passing through the questionId through as an extra in the camera intent and receive it in the questionnaire activity where it then scrolls through the questions it's added and if it's the same one, it adds the picture to the question it's associated to.
The way it adds questions is by having a viewgroup which just inserts at a part for each of them.
This the relevant part that launches the camera (I've tried using it without a bundle, too). This is inside a subclass of a BaseQuestion which is just a subclass of a linearlayout:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Bundle bundle = new Bundle();
bundle.putInt("questionId", getQuestionId());
intent.putExtras(bundle);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
Environment.getExternalStorageDirectory(), "image.tmp")));
((Activity)getContext()).startActivityForResult(intent, TAKE_PHOTO);
This is the relevant part that handles the result which is in an activity.
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
Bitmap image = null;
switch (requestCode)
{
case TAKE_PHOTO:
{
if (resultCode == RESULT_OK)
{
InputStream inputStream = null;
File file = new File(Environment.getExternalStorageDirectory(),
"image.tmp");
try {
inputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (inputStream == null) {
Uri uri = imageReturnedIntent.getData();
try {
inputStream = getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
image = createScaledBitmapFromStream(inputStream, 200, 300);
Bundle bundle = imageReturnedIntent.getExtras();
if (bundle != null)
{
int questionId = bundle.getInt("questionId");
for (BaseQuestion questionView : questionViews)
{
if (questionId == questionView.getQuestionId())
{
questionView.setResponse(image);
}
}
}
}
else if (resultCode == Activity.RESULT_CANCELED)
{
Log.d("something", "something");
}
break;
}
}
}
EDIT: Solved, might not be clear from answer
I made questionIdForResult in my superclass which I set to -1. I then set it to the questionId when it runs startActivityForResult, and then in onActivityResult, I check each question if their questionIdForResult matches their questionId and if it does, use that one. I then set it back to -1 to make sure if you have two, it doesn't go to the other one.
Your approach will not work, as there is no requirement for any camera app to magically copy extras from the incoming Intent to the result Intent. In fact, I will be rather surprised if any camera activity does this.
You could store questionId() in a data member of the activity (e.g., questionIdForTheNextActivityResult), then use that value in onActivityResult(). Bear in mind, though, that taking a picture using a third-party app means that your process may be terminated before you get control again, so be sure to save that data member via onSaveInstanceState() and restore it via onRestoreInstanceState().

Android: overriding an intent's option menu

Suppose i wrote a camera app by using and intent(MediaStore.ACTION_IMAGE_CAPTURE) and i notice that when i run the app, the option menu displays "Edit shortcuts", how can i add on to this option menu or completely override the option menu to my own?
Below are snippet of my code:
public class GPSCam extends Activity implements LocationListener,
GpsStatus.Listener {
private Intent camIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gpscam);
...
...
this.startCamera();
}
protected void startCamera() {
...
// create camera intent
camIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// define where to keep the photo
camIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
// this method will call onActivityResult() upon finishing an activity
// i.e. image captured
startActivityForResult(camIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
...
...
...
}
}
You cannot modify the options menus of other applications. If you do not want to use another application for taking photos, you are welcome to use the Camera object and take photos yourself.

How to go back from calling intent

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.

Categories

Resources