In my Android application, I need to open a link in Browser. This page can receive some data just via POST. Could I add these parameters (data) to the intent which start the browser?
Do you know if this is possible? If it is, could you give my a hint?
Use a webview:
WebView webview = new WebView(this);
setContentView(webview);
byte[] post = EncodingUtils.getBytes("postvariable=value&nextvar=value2", "BASE64");
webview.postUrl("http://www.geenie.nl/AnHeli/mobile/ranking/demo/index.php", post);
Intents sent to the browser can contain more than just a URL. In older versions of android it was possible to package extra POST data in the intent, in newer versions that capability is gone but one can send extra header data for a GET (which can be just about anything representable as a string) in the intent delivered to the browser.
try{
String finalUrl = "javascript:" +
"var to = 'http://the_link_you_want_to_open';" +
"var p = {param1:'"+your_param+"',param2:'"+your_param+"'};" +
"var myForm = document.createElement('form');" +
"myForm.method='post' ;" +
"myForm.action = to;" +
"for (var k in p) {" +
"var myInput = document.createElement('input') ;" +
"myInput.setAttribute('type', 'text');" +
"myInput.setAttribute('name', k) ;" +
"myInput.setAttribute('value', p[k]);" +
"myForm.appendChild(myInput) ;" +
"}" +
"document.body.appendChild(myForm) ;" +
"myForm.submit() ;" +
"document.body.removeChild(myForm) ;";
Uri uriUrl = Uri.parse(finalUrl);
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
PackageManager packageManager = this.getPackageManager();
browserIntent.setData(uriUrl);
List<ResolveInfo> list = packageManager.queryIntentActivities(browserIntent, 0);
for (ResolveInfo resolveInfo : list) {
String activityName = resolveInfo.activityInfo.name;
if (activityName.contains("BrowserActivity")) {
browserIntent =
packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName);
ComponentName comp =
new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
browserIntent.setAction(Intent.ACTION_VIEW);
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
browserIntent.setComponent(comp);
browserIntent.setData(uriUrl);
}
}
this.startActivity(browserIntent);
}catch (Exception e){
e.printStackTrace();
txtHeader.setText(e.toString());
}
I believe that there is a little misconception in the question. What is missing is the purpose that you need of the POST instead of GET.
If you admit I will make few assumptions that could be common in this context:
You need to hide the actual variables from history
You Need some interaction with server before user gets control
You cannot control the server itself and it uses (on purpose) POST requests
Any of those options or requirements implies some additional processing that is distinct from usual browser use case (which is to give full control over the processing and interaction). It seems that you are actually asking for Machine to Machine (M2M) communication with eventual HTML output.
If that renders to be true, then using some OKHttp, HTTPURLConnection, Apache HTTP Client, etc. is the right choice. Rather then invoking the browser via Intent, that has close to zero messaging capabilities (just fire and forget - in case of http:...). It actually requires some analysis of the data flow (sequence diagram might help) and then engineering of that process into M2M or assisted M2M interaction.
If the server you are using to interact with is your own, then why you do not create some REST/JSON/SOAP or other M2M API to make remote method calls (RPC/RMI/...). It is not that complex as it might look (e.g.: http://coreymaynard.com/blog/creating-a-restful-api-with-php/ or https://docs.phalconphp.com/pt/latest/reference/tutorial-rest.html)
Alternative would be to make your M2M interaction rather on your APP server, because then the eventual changes to the BE server data flow could be reflected without app change. By this you would be actually shifting the M2M communication partially to server side.
Note: Using application to interact with 3rd party servers might have some legal implications. In fact those server might not allow other use than through browser (human detection = captcha, User-Agent detection). In such case you have to negotiate with the server owner.
Related
In my Android application, I need to open a link in Browser. This page can receive some data just via POST. Could I add these parameters (data) to the intent which start the browser?
Do you know if this is possible? If it is, could you give my a hint?
Use a webview:
WebView webview = new WebView(this);
setContentView(webview);
byte[] post = EncodingUtils.getBytes("postvariable=value&nextvar=value2", "BASE64");
webview.postUrl("http://www.geenie.nl/AnHeli/mobile/ranking/demo/index.php", post);
Intents sent to the browser can contain more than just a URL. In older versions of android it was possible to package extra POST data in the intent, in newer versions that capability is gone but one can send extra header data for a GET (which can be just about anything representable as a string) in the intent delivered to the browser.
try{
String finalUrl = "javascript:" +
"var to = 'http://the_link_you_want_to_open';" +
"var p = {param1:'"+your_param+"',param2:'"+your_param+"'};" +
"var myForm = document.createElement('form');" +
"myForm.method='post' ;" +
"myForm.action = to;" +
"for (var k in p) {" +
"var myInput = document.createElement('input') ;" +
"myInput.setAttribute('type', 'text');" +
"myInput.setAttribute('name', k) ;" +
"myInput.setAttribute('value', p[k]);" +
"myForm.appendChild(myInput) ;" +
"}" +
"document.body.appendChild(myForm) ;" +
"myForm.submit() ;" +
"document.body.removeChild(myForm) ;";
Uri uriUrl = Uri.parse(finalUrl);
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
PackageManager packageManager = this.getPackageManager();
browserIntent.setData(uriUrl);
List<ResolveInfo> list = packageManager.queryIntentActivities(browserIntent, 0);
for (ResolveInfo resolveInfo : list) {
String activityName = resolveInfo.activityInfo.name;
if (activityName.contains("BrowserActivity")) {
browserIntent =
packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName);
ComponentName comp =
new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
browserIntent.setAction(Intent.ACTION_VIEW);
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
browserIntent.setComponent(comp);
browserIntent.setData(uriUrl);
}
}
this.startActivity(browserIntent);
}catch (Exception e){
e.printStackTrace();
txtHeader.setText(e.toString());
}
I believe that there is a little misconception in the question. What is missing is the purpose that you need of the POST instead of GET.
If you admit I will make few assumptions that could be common in this context:
You need to hide the actual variables from history
You Need some interaction with server before user gets control
You cannot control the server itself and it uses (on purpose) POST requests
Any of those options or requirements implies some additional processing that is distinct from usual browser use case (which is to give full control over the processing and interaction). It seems that you are actually asking for Machine to Machine (M2M) communication with eventual HTML output.
If that renders to be true, then using some OKHttp, HTTPURLConnection, Apache HTTP Client, etc. is the right choice. Rather then invoking the browser via Intent, that has close to zero messaging capabilities (just fire and forget - in case of http:...). It actually requires some analysis of the data flow (sequence diagram might help) and then engineering of that process into M2M or assisted M2M interaction.
If the server you are using to interact with is your own, then why you do not create some REST/JSON/SOAP or other M2M API to make remote method calls (RPC/RMI/...). It is not that complex as it might look (e.g.: http://coreymaynard.com/blog/creating-a-restful-api-with-php/ or https://docs.phalconphp.com/pt/latest/reference/tutorial-rest.html)
Alternative would be to make your M2M interaction rather on your APP server, because then the eventual changes to the BE server data flow could be reflected without app change. By this you would be actually shifting the M2M communication partially to server side.
Note: Using application to interact with 3rd party servers might have some legal implications. In fact those server might not allow other use than through browser (human detection = captcha, User-Agent detection). In such case you have to negotiate with the server owner.
I want my app to give sample images based on what the user typed.
I created a custom search engine, already ticked "search entire web but emphasise...", and ticked "Image Search".
Created an html GET request as per Google's instructions.
String start = "start=0";
// looking for
String strNoSpaces = toSearchIn.replace(" ", "+");
String url2 = "https://www.googleapis.com/customsearch/v1?"
+ "key=" + keyBrowser
+ "&cx=" + cx
+ "&q=" + strNoSpaces
+ start
+ "&searchtype=image"
+ "&alt=json";
return url2;
and it all works well, I retrieve the image URLs and inflate the grid view.
The problem is the quality of results. It is nowhere near the relevance of what you see on the main google.com search results, and it was kind of my goal. The results that I am getting are rather disappointing and make the whole feature not worth it.
For comparison
my "party" results
Normal search results
Can this be changed with some parameters? I already tried most of them without much difference
I am working in Android and using Jsoup for cwaling some data from internet. I am unable to find the exact class name where the comment lies in the below defined code. I tried with disqus_thread , dsq-content,ul-dsq-comments and dsq-comment-body by going to the source page of url but not any one returned the comments.
public static void main(String[] args) {
Document d;
Elements lin = null;
String url = "http://blogs.tribune.com.pk/story/39090/i-hate-materialistic-people-beta-but-i-love-my-designer-clothes/";
try {
d = Jsoup.connect(url).timeout(20*1000).userAgent("Chrome").get();
lin = d.getElementsByClass("dsq-comment-body");
System.out.println(lin);
} catch (IOException e) {
e.printStackTrace();
}
int i=0;
for(Element l :lin){
System.out.println(""+i+ " : " +l.text());
i++;
}
}
That's because the HTML that makes up the comments is generated dynamically after the page has been loaded, using Javascript. When the page is loaded the comment HTML doesn't exist, so Jsoup cannot retrieve it.
To get hold of the comments you have 3 options:
1) Use a web-crawler that can execute javascript. Selenium Webdriver (http://www.seleniumhq.org/projects/webdriver/) and PhantomJS (http://phantomjs.org/) are popular options here. The former works by hooking into a browser implementation (e.g. Mozilla Firefox) and opening the browser programmatically. The latter does not open a browser and executes the javascript by using Webkit instead.
2) Intercept the network traffic when opening the site (here you can probably use your browser's built-in network tab) and find the request that fetches the comments. Make this request yourself and extract the relevant data to your application. Bear in mind that this will not work if the server serving the comments requires some kind of authentication.
3) If the comments are served by a specialized provider with an openly accessible API, then it might be possible to extract them through this API. The site you linked to uses Disqus to handle the comment section so it might be possible to hook into their API and fetch them this way.
I am having a curious problem that perhaps someone has insight into. I encode a query string into a URL on Android using the following code:
request = REQUEST_BASE + "?action=loadauthor&author=" + URLEncoder.encode(author, "UTF-8");
I then add a few other parameters to the string and create a URI like this:
uri = new URI(request);
At a certain point, I pull out the query string to make a checksum:
uri.getRawQuery().getBytes();
Then I send it on its way with:
HttpGet get = new HttpGet(uri);
On the Appengine server, I then retrieve the string and try to match the checksum:
String query = req.getQueryString();
Normally, this works fine. However, there are a few characters that seem to get unencoded on the way to the server. For example,
action=loadauthor&author=Charles+Alexander+%28Ohiyesa%29+Eastman×tamp=1343261225838&user=1479845600
shows up in the server logs (and in the GAE app) as:
action=loadauthor&author=Charles+Alexander+(Ohiyesa)+Eastman×tamp=1343261226837&user=1479845600
This only happens to a few characters (like parentheses). Other characters remain encoded all the way through. Does anyone have a thought about what I might be doing wrong? Any feedback is appreciated.
I never did find a solution for this problem. I worked around it by unencoding certain characters on the client before sending things to the server:
request = request.replace("%28", "(");
request = request.replace("%29", ")");
request = request.replace("%27", "'");
If anyone has a better solution, I am sure that I (and others) would be interested!
URLEncoder does not encode parentheses and certain other characters, as they are supposed to be "safe" for most servers. See URLEncoder. You will have to replace these yourself if necessary.
Example:
URI uri = new URI(request.replace("(","%28"));
If a lot of replacements are needed, you can try request.replaceAll(String regularExpression, String replacement). This, of course, requires knowledge of regular expressions.
Searched a lot.
I have an app. App logins on server and receive some cookies, then it can execute some POST requests with them (e.g. to get user profile). I want to store them between sessions (it means I can restart a device, run app and get profile without extra logging in). Or, in other words, how to create persistent cookie storage?
I'm using the only DefaultHttpClient and there are no WebViews. But I should initialize this client after creation with some cookies. I should store it in file or what? Are there ways to do it in iOS way without weird hacks, storing in files/DBs and manual filling CookieManagers?
Now I'm using a PersistentCookieStorage class for those purposes. I create a singleton when the app is launched. It stores cookies in SharedPreferences.
An implementation of java.net.CookieStore for providing persistent cookies.
Use this https://gist.github.com/manishk3008/2a2373c6c155a5df6326
Storing some data in CookieManager:
void populateCookieStore(URI uri)
throws IOException {
CookieManager cm = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cm);
Map<String,List<String>> header = new HashMap<>();
List<String> values = new ArrayList<>();
values.add("JSESSIONID=" + SESSION_ID + "; version=1; Path="
+ URI_PATH +"; HttpOnly");
values.add("CUSTOMER=WILE_E_COYOTE; version=1; Path=" + URI_PATH);
header.put("Set-Cookie", values);
cm.put(uri, header);
}