how to call activity from inputmethodservice and get response - android

I have a soft keyboard as a inputmethodservice calling an activity. A button is pressed and a scanner is activated. The scanner activity captures a set of data then returns the data to the inputmethodservice for filling in a text field on a browser.
How do I return the scan value of the activity back to the inputmethodservice?
Thanks for any help.

You generally can't do this from a Service. Because a Service is not an Activity, it can not receive results from an Activity, and thus does not have startActivityForResult().
In fact you probably don't want to do this. Starting an activity is at best going to be a clunky experience -- a user doing input into a field doesn't really want to context switch out to another application's activity as part of their input.
Worse, this opens the door to a lot of ugly interactions. For example, if they press home or use a notification or recent apps to switch to another application, what will happen to your activity? Probably nothing good.
Instead I would recommend just showing a dialog as part of the IME -- use the Dialog class and set its window type to TYPE_INPUT_METHOD_DIALOG. This will display on top of your IME, allowing you to interact with the user without disrupting the editing session. For example, you'll want to set this dialog to not take input focus with FLAG_NOT_FOCUSABLE so the text editing session where the user is performing input is not disrupted.
And honestly the best thing to do is to have your UI incorporated into the IME itself.

Here is a code to test the solution using Dialog:
// 1. CREATE THE DIALOG
val builder: AlertDialog.Builder = AlertDialog.Builder(this, R.style.Theme_AppCompat_Light)
builder.setTitle("Title").setMessage("This is the message for the user. ")
val mDialog = builder.create()
// 2. SET THE IME WINDOW TOKEN ATTRIBUTE WITH THE TOKEN OF THE KEYBOARD VIEW
mDialog.window?.attributes?.token = this.mKeyboardView.windowToken
// 3. SET THE TYPE OF THE DIALOG TO TYPE_APPLICATION_ATTACHED_DIALOG
mDialog.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG)
// 4. SHOW THE DIALOG
mDialog.show()

What you want is startActivityForResult(yourIntent, SCAN_VALUE). Your IME will launch the activity, which will then return a value to the IME.
So your service will do something like the following:
Intent yourIntent = new Intent(this , YourActivity.class);
this.startActivityForResult(yourIntent, SCAN_VALUE);
Also in your Service, you'll have to call onActivityResult():
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode) {
case SCAN_VALUE:
if (resultCode == RESULT_OK) {
//TODO: Create some functionality here!
break;
}
Okay, so now let's tackle your launched activity. You'll have to modify this to fit your purposes, but here's how you would send a value back from, say, a ListAdapter. You didn't post your code, so it's tough to know exactly what you're doing.
Object o = this.getListAdapter().getItem(position);
String scanValue = o.toString();
Intent returnIntent = new Intent();
returnIntent.putExtra("ScanValue", scanValue);
setResult(RESULT_OK,returnIntent);
finish();
This will return a value to the IME launching the activity as a string. Again, if you post your code, I can give you more exact instructions. I hope this helps you wrap your mind around startActivityForResult() in the meantime, though.

Related

ANDROID: open an URL in external browser, while continuing the application

In the starting activity of my app I show a dialog to user and ask if he wants to see some contents in my website or not.
If he clicks No, the dialog disappears and I call continueActivity() to do some process and go from current activity to MainActivity.
If he click yes, I want to open the webpage in the external browser and again I call continueActivity() to do some process and go from current activity to MainActivity.
The problem is in positive state. This is my code in positive state:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.aaa.ir"));
startActivity(browserIntent);
continueActivity();
Because of calling continueActivity(), the external browser can't open and if I don't call continueActivity(), the URL opens in the external browser and the app sticks in the current activity.
So how could I open the URL and at the same time, continue the process and go to other activities.
I usually use
startActivityForResult(browserIntent, BROWSER_REQUEST);
and override onActivityResult(int reqCode, int resultStat, Intent intent)
if(reqCode == BROWSER_REQUEST) {
continueActivity();
}
Once you call startActivity, your current Activity will follow through the exit of the Activity lifecycle. This is unavoidable.
If you have processing you want to continue in the meantime, you should consider a Service. If you want the App to return to its current state, you need to store relevant data and load your Activity to its previous state (or next intended state).
in both ways ContinueActivity is opening. i don't know you architecture. You could just add to intent some extra like
intent.putBoolean("openExternalLink", dialogResultHere);
Then in continueActivity you will got this intent like
getIntent().getBoolean("openExternalLink")
also dont forget to delete this option, otherwise you will open browser each time after Activity recreation (screen rotation, minimize, etc.)
getIntent().removeBoolean("openExternalLink");
P.S. signatures of methods could be littlebit different, but general idea is here

android one time login system

I am trying to design a one time login system.
On the loginActivity the user enters a phone number to which I send a secret code thru SMS
On the confirmationActivity the user enters the secret code.
If the secret code is successful, I want to finish both confirmationActivity and loginActivity. To do that from loginActivity I do
Intent intent = new Intent(this, ConfirmationActivity.class);
startActivityForResult(intent, EXIT_CODE);
Then again in loginActivity I call
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == EXIT_CODE) {
finish();
}
}
}
To test whether my system works, after registration, I click on the back button:
Expected behavior: Not being able to go back or close the app
Actual behavior: go back to the loginActivity (notice that it skips the confirmationActivity)
My hope is that once a user successfully registers they should never again get access to either the confirmationActivity or the loginActivity. And that when they close my app and restart it, it skips those two pages and take the user directly to the home page.
Note: It looks like the onActivityResult method is never called. I place a few println calls in there and they are never printed on LogCat.
DISCLAIMER: Last time I asked a question and showed a code snippet, one respondent got distracted and started talking about the snippet instead of addressing the question. The snippet here is just to show what I have tried. Obviously it has not solved the problem. Thank you.
One possible solution could be:
Instead of opening the app with LoginActivity you create a new one called FirstActivity.
In this activity you check if you have set a flag in sharedPreferences.
If this check is true then continue to your logged-in Activity.
If this check returns false start LoginActivity. After a User has succesfully entered the "secret", you should set a flag in the sharedPreferences. Next time the user opens the app the flag in sharedPreferences will be set a you will know that the user is already registered.
Any questions? comment below

Android Services, Activities and Handlers?

Im developping an Android Service in Android that needs to pop-up a new dialog box for confirmation.
I can popup a new activity using Intent and Context
Intent myIntent = new Intent(context, ConfirmationActivity.class);
But then I need to handle the option selected in the dialog box (OK or Cancel).
Any suggestion?
Note: Not developing for smartphones.
Update: I need to return the result to the place I call the Dialog.
A service should not pop up anything at all. Imagine the user is in the middle of a phone call when your dialog pops up.
If you need a confirmation from the user the best thing you can do is to use the NotificationManager and use a PendingIntent to launch an Activity. The Activity can still have a dialog style if you like.
Control flows back from the Activity to your Service then, so when the user presses ok or cancel you would either call a bound interface or use SharedPreferences to tell the service about the user's choice.

Refresh activity and re-open

This is my first post, so please be nice :)
I have a question and no one gave the answer in the post I've seen.
My app has a list and a button to open an activity, this activity creates a new item to show in the list of the previous activity when pressing the button Create.
How can I do this?
This is the code I made for the first button:
intent = new Intent(this.getBaseContext(), NewTestActivity.class);
this.finish();
startActivity(intent);
and this is the code to go back an refresh:
Intent intent = new Intent(getBaseContext(), TestListActivity.class);
startActivity(intent);
But the code to goback is useful, because the activity don't refresh.
I have to call the new activity in a diferent way? Or go back to previus activity in a diferent way? Or go back normally and refresh the activity when I'm back in the previus activity?
Well...this is all.
Sorry for my bad english and, if this question has been answered in another thread, give me the link to read, because I can't find it :)
PS: I started with android in December.
Thanks for your help.
When you are going to start new activity you shouldn't close a current one until you actually need this behaviour. (remove this.finish(); row from your code)
Also you shouldn't close an active activity manually until you actually need it. When the user presses the "back" button on the device Android pops the previous activity from the "back stack". Read once more Activity documentation.
According to your description you have a list of elements. So in order to refresh the list you need to update your dataset and notify the list about it by ListView.notifyDataSetChanged() method call.
Before getting to a real answer, I'd like to show some improvements to your code.
First, when creating an Intent (or when you need a context in general) from an Activity there is no need to call getBaseContext(), you can just use this:
intent = new Intent(this, NewTestActivity.class);
Second, android is good at handling Activities, you do not have to close your first activity manually with finish(). Android will automatically pause or stop your first activity and bring it back when you return to it.
Third, in your case you might want to use startActivityForResult() instead of startActivity() for reasons I will explain below.
This will make your code look like the following:
private static final int MY_REQUEST_CODE = 33487689; //put this at the top of your Activity-class, with any unique value.
intent = new Intent(this, NewTestActivity.class);
startActivityForResult(intent, MY_REQUEST_CODE);
Now, the startActivityForResult() starts an activity and waits for a result from that new Activity. When you call finsih() in the new Activity you will end up in the first Activitys onActivityResult()-method, with data supplied from the new Activty that is now closed:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode != MY_REQUEST_CODE) return; //We got a result from another request, so for this example we can return.
if(resultCode != RESULT_OK) return; //The user aborted the action, so we won't get any data.
//After the above if-statements we know that the activity that gives us a result was requested with the correct request code, and it's action was successful, we can begin extracting the data, which is in the data-intent:
Item item = (Item) data.getSerializableExtra("customData"); //casts the data object to the custom Item-class. This can be any class, as long as it is serializable. There are many other kinds of data that can be put into an intent, but for this example a serializable was used.
itemList.add(item); //This is the list that was specified in onCreate()
//If you use an Adapter, this is the place to call notifyDataSetChanged();
}
For this all to work, we need to do some things in the second Activity:
When the item has been created, we must set a result:
//We begin by packing our item in an Intent (the Item class is an example that is expected to implement Serializable)
Item theCreatedItem; //This is what was created in the activity
Intent data = new Intent();
data.putSerializable(theCreatedItem);
setResult(RESULT_OK, data);
finish();
This should return to the first Activitys onActivityResult()-method with the item, as explained above.

Android Default application

i would like to know how to show
the check box that makes some application the
default in the createChooser dlg.
thanks in advance.
yes David i would like to know how to clear the app from being default. also i would like to know whether i can call any intent if i know its action, category, package and "class name", can I?
I actually tried to call some activity i previously known its intent contents put some SECURITY EXP. raised. why?
Your question isn't 100% clear to me, so forgive me if I'm answering the wrong question. It sounds like you want to either:
Pop up the dialog that lets the user select your activity as the default to handle some intent; or
Check if your activity is the default for an intent.
I'll answer both.
To pop up the dialog that lets the user select your activity as the default to handle some intent, simply call startActivity() with that intent. If for example you wanted to register yourself as the default home screen you would simply:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
1 of 3 things would happen.
Either there is no default specified (and if a user just installed your app, it will clear the default value) and thus the pop up will appear, or you're already the default or someone else is the default.
If you're already the default, then awesome, just figure out how to handle the intent this once (maybe add an EXTRA that explains that this was just a test so your activity knows to finish() immediately).
If someone else is the default you'll need to walk the user through clearing defaults for that app. If no one is the default you may want to throw up a Toast notification that explains what the user should do.
Toast.makeText(this,
"Please check 'Use by default for this action' and then press 'MyActivity'",
Toast.LENGTH_LONG).show();
These are all sort of messy situations to handle and it would be better to check first before calling startActivity(). To do that, use ResolveInfo.
ResolveInfo res = getPackageManager().resolveActivity(intent, 0);
// Got to be a better way to determine if there is no default...
if (res.activityInfo.packageName.equals("android")) {
// No default selected
} else if (res.activityInfo.packageName.equals(getPackageName())) {
// We are default
} else {
// Someone else is default
}
Hope this helps! If you want to know about how to make it easy for the user to clear another app from being default, let me know.

Categories

Resources