How to distingue between inputs inside onCreateInputConnection from WebView? - android

I have an excerpt of my app that loads a HTML - which I do not have any access to change - with three inputs: e-mail, password and a validation code on a WebView. The last one will always be numbers. I want to show the numeric keyboard only for this last input element. I'm doing that by extending a WebView class and overriding this method as shown below:
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
BaseInputConnection ic = new BaseInputConnection(this, true);
outAttrs.inputType = InputType.TYPE_CLASS_NUMBER; // Tells the keyboard to show the number pad
return ic;
}
Problem is, I do not know which flag I can check in order to differ the three different inputs I have on the HTML, so I can run this code only for the validation code input element. Any ideas?

Capture the before focus event in javascript, store the field id which is about to get focus and then use that value in onCreateInputConnection to make decisions on what type of keyboard to show.
If you don't have access to change the source html you can inject your own javascript to set the focusin handler.
For example;
public class MyWebView extends WebView
{
protected String m_szFocusInputID = "";
public void onStartLoad()
{
WebSettings oWebSettings = getSettings();
oWebSettings.setJavaScriptEnabled(true);
...
m_oClient = new WebViewClientEx();
setWebViewClient(m_oClient);
...
addJavascriptInterface(new JSBridge( ), "MyApp");
loadUrl("file:///android_asset/myfile.html");
}
#Override
public InputConnection onCreateInputConnection(EditorInfo oAttrs)
{
InputConnection oConn = super.onCreateInputConnection(oAttrs);
if ("someid".compareTo(m_szFocusInputID) == 0)
{
oAttrs.inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL;
}
return oConn;
}
private class WebViewClientEx extends WebViewClient
{
#Override
public void onPageFinished(WebView oView, String szUrl)
{
evaluateJavascript("$('#myinput1').focusin(function() { MyApp.onFocusIn(this.id); });", null);
}
}
public class JSBridge extends Object
{
...
#android.webkit.JavascriptInterface
public void onFocusIn(String szFocusInputID)
{
m_szFocusInputID = szFocusInputID;
}
}
}

Related

How to get the WebView object inside a custom WebViewClient?

I created a new function in a CustomWebViewClient class that needs to use the webViewObject. However, I dont seem to find a way how to access it without passing the parameter to the constructor.
This is what the class looks like:
public class CustomWebViewClient extends WebViewClient {
public CustomWebViewClient(){
myFunction();
}
private myFunction(){
//needs to use the webView object
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String check_url){
//some code here
return false
}
}
This is how to set the custom class to a webViewObject:
CustomWebViewClient myWebViewClient = new CustomWebViewClient();
webViewObject.setWebViewClient(myWebViewClient);
Notice that shouldOverrideUrlLoading function gets the parameter. So its possible its there somewhere.

Using common function in multiple activity android

I want to use common function in multiple activity. How can I achieve this?
In my application I am displaying a Dialog box which have some data coming from some api. And this Dialog box, used in multiple activities. Right now I have implemented same Dialog box in all activities. Now I want common Dialog box for all activities. I am using this Dialog box in activity as well in adapter.
How could I do this? Using extends or using fragment.
I am already extending some class so I can not extend again( As I read, we can not extends more than one class.).
Also I want to pass some value to this function and based on return value I want to call another function.
private boolean allGroupsEdit(final String type) {
String allGroups = "allGroups";
final String url = Constants.CONSTANT_SERVER_URL + Constants.CONSTANT_GET_GROUPS_URL;
final ProgressDialog dialog = new ProgressDialog(context);
dialog.setMessage(context.getResources().getString(R.string.please_wait));
dialog.show();
StringRequest allGroupsRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
final SharedPreferences sharedPreferencesRemember = PreferenceManager.getDefaultSharedPreferences(context);
sessionGroupId = sharedPreferencesRemember.getString(Constants.CONSTANT_session_group_id, "");
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.optJSONArray(Constants.CONSTANT_data);
int a = jsonArray.length();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject schObj = jsonArray.optJSONObject(i);
schData = schObj.optJSONArray(Constants.CONSTANT_data);
}
dialog.dismiss();
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setContentView(R.layout.dialog_checkbox_options);
Window window = dialog.getWindow();
window.setLayout(DrawerLayout.LayoutParams.MATCH_PARENT, DrawerLayout.LayoutParams.WRAP_CONTENT);
if(..someting){
editPublicComments(type);
}else{
editPublicPosts(type);
}
}catch(){}
}
}
Note: This a very long function so I am pasting some code for basic understand. If u need anything more detail let me know. Thanks in advance and editing and suggestions are welcome.
Edit_1: I want this whole function to be common.
Edit_2: How to return value to activity from utils ?
Edit_3: Now I created a static function in a class and I am able to call it from my activity. Now I want call another function based on common function result. (I am using SharedPreferences to store value of common function).
But in my activity where I called a common function, I doesn't execute common function first. It call another function then It call common function and after completing common method, it doesn't call another method again.
All I want to call another function based on result of common function which is true or false
boolean abab = CommonGroupBox.allGroupsEdit(context,"share", selectedPostId, localGrpArray);
if (abab){
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
editPublicComments(qType);
}else{
ediComments(qType);
}
else{
boolean pubFlag = pref.getBoolean("isPublicFlag", false);
String qType = pref.getString("questionType","0");
if (pubFlag) {
PublicComments(qType);
}else{
Comments(qType);
}
}
Here it doesn't call CommonGroupBox.allGroupsEdit firsts. It is called after if and else loop.
Just create a normal java class
public class Utility {
//your common method
public static void showDialog(Context context,int type){
//TODO task
}
}
Now you can use the showDialog method any where in your application
Utility.showDialog(ctx,type);
You can create an abstract class which extends AppCompatActivity, implement your method there and make all your other activities extend this class:
public abstract class BaseActivity extends AppCompatActivity {
protected boolean allGroupsEdit(final String type) {
// ...
}
// Other methods
}
Then implement your activity as :
public class MainActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
allGroupsEdit("Some type");
}
...
To create a Utility Class:
1) Create a Java file with name AppUtil which extends Activity.
2) Select a common method that you are going to use in your Application.
3) Write the function in AppUtil java file
4) Make all the function as static in your Java file so it can be easy to call inside your activity (example: AppUtil.yourMethod() )
5) Pass the context of your Activity.
Here is a simple example to check internet connection:
public class AppUtilities extends Activity {
public static boolean isInternetConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting() &&
netInfo.isAvailable();
}
}
And you can easily call this method from anywhere in your Application
example ::
AppUtilities.isInternetConnected(YourActivity.this);

How do I get integer String output into Android Studio's Logcat?

I have a bunch of EditTexts that are set up with int Strings to capture their length. I want to show the lengths in LogCat to confirm they have been set up correctly. I read about using LogCat, tags and how to filter but need some advice on how to add Log code to get output to LogCat.
Here is an example of the int String I am looking to calculate length for:
public class CardViewActivity extends AppCompatActivity {
private String tag = "CLOCKS";
private ListenerEditText eListenerEditText;
eListenerEditText.setKeyImeChangeListener(new KeyImeChange() {
#Override
public boolean onKeyIme(int keyCode, KeyEvent event) {
int stringNotes2 = eListenerEditText.getText().toString().trim().length();
Log.d("CLOCKS", String.valueOf(stringNotes2));
Log.d() must be called in somewhere like onCreate(..) {..} or some type of method.
for example,
// This is wrong
public class Hello {
Log.d("hello","hi");
...
}
Make sure you call methods in some type of methods.
// This is correct
public class Hello extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Hello","Hi");
...
}
...
}
Hope this helps
You shoud declare your log tag:
private static final String MYAPPTAG= YourActivity.class.getName();
Then you put the log code in a method:
Log.d(MYAPPTAG, String.valueOf(stringDueDate));
You will need to make sure you set your filter properly in logCat settings.
I suggest you to concatenate with a string to make sure something prints to the console just incase the value is null, for example:
Log.d(MYAPPTAG, "stringDueDate = " + stringDueDate);
Try this -
public class CardViewActivity extends AppCompatActivity {
private static final String TAG = "CLOCKS";
private ListenerEditText eListenerEditText;
eListenerEditText.setKeyImeChangeListener(new KeyImeChange() {
#Override
public boolean onKeyIme(int keyCode, KeyEvent event) {
int stringNotes2 = eListenerEditText.getText().toString().trim().length();
Log.d(TAG, "Length - " + stringNotes2));
}
}
If this doesn't work then there must be something wrong with your listener. I'll highly recommend to use TextWatcher on EditText over KeyListener.
Log.i: Use this to post useful information to the log. For example: that you have successfully connected to a server. Basically use it to report successes.
Log.i(String tag, String msg);

Android interfacing

I always have this problem of java.lang.IllegalStateException:Could not execute method of the activity. I was planning to perform an android component event (ex. Button event - indicating the number of times this button was clicked). Here's the code snippet for this problem:
interface Selection {
public void clicked();
}
public class ParentClass extends FragmentActivity {
// fTabs : FragmentTabHost
// tabs : Map<String, Selection>
private void initialize() {
// fistFrag : FirstChildClass = new FirstChildClass()
// secondFrag : SecondChildClass = new SecondChildClass()
tabs.put("first", firstFrag);
tabs.put("second", secondFrag);
fTabs.add(fTab.newTabSpec("first").setTitle("First"), firstFrag.getClass(), null)
fTabs.add(fTab.newTabSpec("second").setTitle("Second"), secondFrag.getClass(), null)
}
#Override
public void onBackPressed() {
tabs.get(fTabHost.getCurrentTabTag()).clicked();
}
}
public class FirstChildClass extends Fragment implements Selection {
// data : TextView
// hit : int = 0
#Override
public void clicked() {
data.setText(String.format("Hit Count: %d", ++hit));
}
}
public class SecondChildClass extends Fragment implements Selection {
// data : TextView
// hit : int = 0
#Override
public void clicked() {
data.setText(String.format("Hit Count: %d", ++hit));
}
}
I've tried to assure of clicked() works view interfacing approach by invoking a message on Logcat and it worked but when I used Button the error above always prompts me. I've checked if data is null and it returned true. I am a little bit confused, I've tried to check nullity of data from the Activity methods is returns false but when I access any method override by an interface it always return true. Is there a way to solve this?
Here's a way my friend told me to solve this problem. Using getSupportFragmentManager. He told me also that creating an Activity or Fragment using its constructor isn't applicable on the Android platform. So I switched by to the conventional way of adding tabs to FragmentTabHost.
#Override
public void onBackPressed() {
//tabs.get(fTabHost.getCurrentTabTag()).clicked();
((Selection) getSupportFragmentManager().findByFragmentByTag(fTabHost.getCurrentTabTag()).clicked();
}

How to cancel a ListPreference click?

I have 3 preference settings:
- An EditTextPreference to enter a web address
- An EditTextPreference to enter a port
- A ListPreference to show some elements from the web page (e.g. http://www.igs-ip.net:2101) defined by the previous 2 settings.
To make this viable, I was thinking to validate the web connection on the click of the 3rd setting. So far, I was able to catch the click to dynamically fill the ListPreference:
ListPreferenceDynamic dlp = (ListPreferenceDynamic)findPreference(strKey);
dlp.setOnClickListner(new ListPreferenceDynamicOnClickListener()
{
public void onClick(ListPreferenceDynamic preference)
{
String[] astr = astrOpenWebPageAndGetInfo(strAddress, strPort);
if (astr != null)
{
preference.setEntries(astr);
preference.setEntryValues(astr);
}
}
});
My problem now is to find a way to prevent to show the ListPreference dialog when there is a problem, let say, with the internet address. I would like only to show a Toast to explain the problem without showing an empty ListPreference dialog.
A bit late but maybe still useful to some of you:
I figured that the OnPreferenceChangeListener can deal with that. Just register one and return true if you want accept the new value or return false if you want to cancel the click:
yourPreference.setOnPreferenceChangeListener((preference, newValue) -> {
if(condition){
showToast();
return false; //cancel the click
}
else return true; //accept the click
});
The parameter newValue determines the new would-be value of your preference.
I was actually after this.
But the ChangeListener triggers after a new value is picked, right?
So it's not really canceling the list which is what I'm after.
I did found a solution which was making a custom ListPreference class and conditionally handle the onClick.
That way if it's set as not active throught the setActive method the list will not show after clicking the option.
public class CustomListPreference extends ListPreference {
private boolean isActive;
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListPreference(Context context) {
super(context);
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public boolean getActive() {
return this.isActive;
}
#Override
public void onClick() {
if (isActive) super.onClick();
}
}

Categories

Resources