I am working on a web Browser, I have a SearchView in it, for user to input queries. I want to differentiate between a search query or a web address. My current code just add http://www. in front of any query that comes in and try to load it.
This is my current code.
String query = search_q;
if(!query.startsWith("www.")&& !query.startsWith("http://")){
query = "www."+ query ;
}
if(!query.startsWith("http://")){
query = "http://"+query;
}
if( Patterns.WEB_URL.matcher(query).matches()){ //checks if the query looks like an URL
web1.loadUrl(query);
}
else
web1.loadUrl("https://www.google.com//search?q=+"+search_q);
The problem is that Patterns.WEB_URL.matcher(query).matches() returns true even if http://www.abc is passed into it.
check
if( Patterns.WEB_URL.matcher(query).matches() && isUrl(query)){ //checks if the query looks like an URL
web1.loadUrl(query);
}
function defintion isUrl:-
public Boolean isUrl(String query){
int a=0;
int onlyfind=0;
for (int i = 0 ; i<query.length() ; i++){
if (query.charAt(i) == '.')
a++;
if(a==1){
onlyfind= i;
}
}
if(a==1){
if(query.substring(0,onlyfind+1).equals("http://www"))
return false;
}
return true;
}
Try validating the url(query) using this method:
//isValidURL(query);
boolean isValidURL(String url) {
try {
new URI(url).parseServerAuthority();
return true;
} catch (URISyntaxException e) {
return false;
}
}
If it returns false, then:
web1.loadUrl("https://www.google.com//search?q=+"+search_q);
I think the best way to validate URL is using regex. Because if you are working on a browser, you should not limit the validation of string queries that starts with www, what if the website is dev.website.com? it is a valid website URL, or what if the address starts with https and not just http?. So I think Try using regex to have a reference pattern in validating if the query string is URL or not:
private boolean isURL(CharSequence searchQuery) {
Pattern urlPattern = Pattern.compile("(https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\w\\D\\S]{2,}|[^\\s]{2,}[a-zA-Z0-9]\\.[^\\s]{2,})");
Matcher matcher = urlPattern.matcher(searchQuery);
return matcher.matches();
}
Then call that method:
String query = search_q;
if(isURL(query)) {
web1.loadUrl(query);
} else {
web1.loadUrl("https://www.google.com//search?q=+"+search_q);
}
Hope this helps.
Related
Understands that using Patterns.WEB_URL.matcher(url).matches() will able to validate if that string is a valid url, however it will required in a full format which contain https: / .com.
In my case, i want to validate if the json return a string in correct format for path e.g /images/slider/my/myImage.jpg; which does not contain https or any. How can i do this?
What i want to do is something like:
if(ImageUrl equal "/images/slider/my/myImage.jpg" FORMAT) {
//Do something here
} else //ImageUrl = myImage.jpg {
//Add "/images/slider/my/" infront of the text
}
P.s: My image link will be like www.abc.com/images/slider/my/myImage.jpg
Use URLUtil to validate the URL as below.
URLUtil.isValidUrl(url)
It will return True if URL is valid and false if URL is invalid.
Another way is given below.
public static boolean checkURL(CharSequence input) {
if (TextUtils.isEmpty(input)) {
return false;
}
Pattern URL_PATTERN = Patterns.WEB_URL;
boolean isURL = URL_PATTERN.matcher(input).matches();
if (!isURL) {
String urlString = input + "";
if (URLUtil.isNetworkUrl(urlString)) {
try {
new URL(urlString);
isURL = true;
} catch (Exception e) {
}
}
}
return isURL;
}
This link will explain how you can check the url is available or not.
For more about URLS please visit this
Please have a try
I must be missing something here. Every example I've seen with Android's 2-way binding is based on a String in the backing data for anything user-enterable, like an EditText.
Handling anything not a String seems somewhat... inelegant. For example, if I have a double in my domain model that needs to be editable, the best binding I've come up with requires a ViewModel with surprisingly a lot of code to interface between the model and the EditText.
Am I missing something key? Should I really need 30 lines of code to interface an EditText with a double? For the sake of discussion, let's consider a currency field, represented as a double, in a two-way bound EditText:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="#={fragModel.startBucks}"
android:id="#+id/editText2"/>
And here's the ViewModel I've had to construct in order to give the EditText a string to bind to.
#Bindable private String startBucksString;
private double localBucks;
public String getStartBucksString() {
double domainBucks = cd.getStartBucks();
// Ignore incoming change of less than rounding error
if( Math.abs(localBucks - domainBucks) < .001 ) return startBucksString;
startBucksString = "";
if( domainBucks != 0)
startBucksString = String.format("$%.2f", domainBucks);
return startBucksString;
}
public void setStartBucksString(String inBuckstr) {
double calcBucks=0;
inBuckstr = inBuckstr.replaceAll( "[^\\d.]", "" );
try {
calcBucks = Double.parseDouble(inBuckstr);
} catch( NumberFormatException e) {
return;
}
// Neglect outgoing change of less than rounding error
if( Math.abs(localBucks - calcBucks) < .001 ) return;
startBucksString = String.format("$%.2f", calcBucks);
localBucks = calcBucks;
cd.setStartBucks(calcBucks);
notifyPropertyChanged(BR.startBucksString);
}
Here, I wrote a simple, compilable example of 2-way binding with a ViewModel. It illustrates the difficulty I had in continuously updating a float in the domain model -- in the end, I decided there's no way to do it without writing a custom TextWatcher for each domain field.
My approach is to delay notifyPropertyChanged method calling using Handles. In this way while the user is typing, the code don't run, then 2,5 seconds after the user has stopped to type last character, the notificationPropertyChanged will be called.
The visual effect is cool, and the user is free to write numbers as he wants.
See these two examples:
Use can use this compact(?) code for each field:
//
// g1FuelCostYear field
//
private double g1FuelCostYear;
#Bindable
public String getG1FuelCostYear() {
return Double.valueOf(g1FuelCostYear).toString();
}
private Handler hG1FuelCostYearDelay = null;
public void setG1FuelCostYear(String g1FuelCostYear) {
// Delayed notification hadler creation
if (hG1FuelCostYearDelay == null) {
hG1FuelCostYearDelay = new Handler() {
#Override
public void handleMessage(Message msg) {
notifyPropertyChanged(it.techgest.airetcc2.BR.g1FuelCostYear);
}
};
} else {
// For each call remove pending notifications
hG1FuelCostYearDelay.removeCallbacksAndMessages(null);
}
// Data conversion logic
try {
this.g1FuelCostYear = Double.parseDouble(g1FuelCostYear);
}
catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
// New delayed field notification (other old notifications are removed before)
hG1FuelCostYearDelay.sendEmptyMessageDelayed(0,2500);
}
This code instead is useful when you use currency converter or percent converter. The user can write a plain double, the code convert to currency string. If the setter is called with the currency string the code is able to convert it as double too.
//
// g1FuelCostYear field
//
private double g1FuelCostYear;
#Bindable
public String getG1FuelCostYear() {
NumberFormat nf = NumberFormat.getCurrencyInstance();
return nf.format(this.g1FuelCostYear);
//return Double.valueOf(g1FuelCostYear).toString();
}
private Handler hG1FuelCostYearDelay = null;
public void setG1FuelCostYear(String g1FuelCostYear) {
if (hG1FuelCostYearDelay == null)
{
hG1FuelCostYearDelay = new Handler() {
#Override
public void handleMessage(Message msg) {
notifyPropertyChanged(it.techgest.airetcc2.BR.g1FuelCostYear);
}
};
} else {
hG1FuelCostYearDelay.removeCallbacksAndMessages(null);
}
boolean success = false;
try {
NumberFormat nf = NumberFormat.getCurrencyInstance();
this.g1FuelCostYear = nf.parse(g1FuelCostYear).doubleValue();
success = true;
}
catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
if (!success) {
try {
this.g1FuelCostYear = Double.parseDouble(g1FuelCostYear);
success = true;
} catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
}
updateG1FuelConsumption();
hG1FuelCostYearDelay.sendEmptyMessageDelayed(0,2500);
}
I succeed login and post my wall.
FB.API("me/photos", Facebook.HttpMethod.POST, Callback, wwwForm);// it works well.
FB.Feed("", "link", "link_name", ~~bulabula~~ );// it works well, too!
//////////////AND PLEASE SEE NEXT CODE. THIS IS PROBLEM.///////////////////
private string FriendSelectorTitle = "Share it with your friends!";
private string FriendSelectorMessage = "invite";
private string FriendSelectorFilters = "[\"all\"]";
private string FriendSelectorData = "{data}";
private string FriendSelectorExcludeIds = "";
private string FriendSelectorMax = "5";
private void CallAppRequestAsFriendSelector()
{
// If there's a Max Recipients specified, include it
int? maxRecipients = null;
if (FriendSelectorMax != "")
{
try
{
maxRecipients = Int32.Parse(FriendSelectorMax);
}
catch (Exception e)
{
//status = e.Message;
Debug.Log(e.Message);
}
}
// include the exclude ids
string[] excludeIds = (FriendSelectorExcludeIds == "") ? null : FriendSelectorExcludeIds.Split(',');
List<object> FriendSelectorFiltersArr = null;
if (!String.IsNullOrEmpty(FriendSelectorFilters))
{
try
{
FriendSelectorFiltersArr = Facebook.MiniJSON.Json.Deserialize(FriendSelectorFilters) as List<object>;
}
catch
{
throw new Exception("JSON Parse error");
}
}
FB.AppRequest(
FriendSelectorMessage,
null,
FriendSelectorFiltersArr,
excludeIds,
maxRecipients,
FriendSelectorData,
FriendSelectorTitle,
Callback
);
}
void Callback(FBResult result)
{
Debug.Log(result.Text);
}
/////////////////////////////////////////////////
it look like works well.
first, pop up friends selector dialog,
and I clicked some friends, and click 'done' button.
it will call 'Callback' Funtion, and
debug.log(FBResult.text); show follow like this.
{"request":"8939391818800568","to":["2446462595631736"],["189238719238719238"]}
but now, I don't know how to use these values. T_T
I think FB.feed(); is well done. So,
I try to
for( int i=0; i<usernum; i++ )
{
FB.feed( "id[user_index]" , bula~bula );
}
but failed.
becuase, fbresult.text is not string!!?
I try to split this string(fbresult.text), to get "to":["userid1 number"], ["userid2 number"]
but I failed and disappointed.
please someone help me.
Anybody who has a good idea???
I really want to send my message(pic or message) to friend's facebook wall.
You canĀ“t post to the wall of a friend anymore, since a very long time. In most (all?) cases this would be considered as spam, so they remove that possibility.
You can use the Send Dialog to send something to a friend, for example.
iam trying to build a class to get any data from webiew (this code is collected from many posts),
i need a function to do the same as "stringByEvaluatingJavascriptFromString" in iPhone
public class JavaScriptInterface
{
String RetValue = "";
public String ExecuteScript(WebView webv, String expression)
{
RetValue = "";
for (int t=0;t<2;t++) // try loadUrl twice (incase the first call fails)
{
webv.loadUrl("javascript:var FunctionOne = function () { var res = " + expression + "; window.HTMLOUT.SendCallback(res); }; FunctionOne();");
for (int i = 0; i < 35; i++) { // wait 3.5 seconds
try {
sleep(100);
} catch (Exception exp) {
}
if (RetValue != "") return RetValue; // if the browser returned a value return this value
}
}
return RetValue; // if the loadUrl fails, the return value is empty string
}
#JavascriptInterface
public void SendCallback(String jsResult)
{
RetValue = jsResult;
}
}
This function works most of times,
however, sometimes there is no return value (just like the script fails or something i dont know why)
is there a way to fix this code?
thank you.
I am posting the answer in case someone has the same problem,
after days of searching i have successfully solved my problem:
1 - WebView init code should be like this
webv = (WebView) findViewById(R.id.webv);
webv.getSettings().setJavaScriptEnabled(true);
webv.setWebChromeClient(new WebChromeClient());
webv.setWebViewClient(new WebViewClient() { });
javaInterface = new JavaScriptInterface();
webv.addJavascriptInterface(javaInterface, "HTMLOUT");
2 - Do not add "setDomStorageEnabled" i dont know why it causes problems to the code above
3 - i was using this code for javascript alerts, but it seems that it causes problems too, so i had to remove it.
webv.setWebChromeClient(new WebChromeClient()
{
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
});
Now it is working better, however, sometimes i have to call the ExecuteScript multiple times to get the result.
i hope someone can explain this problem.
I have been able to pull the Facebook newsfeed for the logged in user using the "me/home" Graph API Call and am displaying the result in an activity.
Now I have been trying numerous methods which will query the post's like column and check if the current user has liked a post to display the status. Essentially, I am setting a drawable to indicate the user has liked a post.
I cannot really post any code that I have tried so far simply because none of them work. And believe me, I have tried literally numerous methods.
I would appreciate if someone could at least prod me in the right direction.
EDIT: This is my latest attempt at querying the likes column and comparing the result with the current user's ID:
This code is where I am checking for likes count and adding them to an ArrayList. This is also where I am running the query to get the likes on the post.
// GET THE POST'S LIKES COUNT
if (json_data.has("likes")) {
JSONObject feedLikes = json_data.optJSONObject("likes");
String countLikes = feedLikes.getString("count");
postLikesCountArrayList.add(countLikes);
// TEST STARTS
// QUERY THE LIKES COLUMN TO CHECK YOUR LIKE STATUS ON A POST
Bundle params = new Bundle();
params.putString(Facebook.TOKEN, Utility.mFacebook.getAccessToken());
Utility.mAsyncRunner.request(finalThreadID + "/likes&limit=200", params, new LikesListener());
// TEST ENDS
} else {
String countLikes = "0";
postLikesCountArrayList.add(countLikes);
}
And this code block is the Listener (a privte class in the same activity) where the results are checked:
private class LikesListener extends BaseRequestListener {
#Override
public void onComplete(final String response, final Object state) {
try {
JSONObject JOLikes = new JSONObject(response);
JSONArray JALikes = JOLikes.getJSONArray("data");
for (int i = 0; i < JALikes.length(); i++) {
JSONObject JOTemp = JALikes.getJSONObject(i);
if (JOTemp.has("id")) {
String getTempID = JOTemp.getString("id");
if (getTempID.equals(initialUserID)) {
Runnable run = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
ImageView postYourLike = (ImageView) findViewById(R.id.postYourLike);
postYourLike.setBackgroundResource(R.drawable.btn_icon_liked);
}
};
TestNewsFeeds.this.runOnUiThread(run);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can use this fql. Replace the post_id
SELECT likes.can_like, likes.user_likes FROM stream WHERE post_id = "1274834235_3976149403543"
response would look like this, if user_likes is true, he has liked it
{
"data": [
{
"likes": {
"can_like": true,
"user_likes": false
}
}
]
}