resolve dns lookup problems in webview - android

Our company's app is mainly a webview embedded in the android/iPhone native app. In some area, the dns lookup always failed which results an error in opening our webview page.
We have found a technology called HttpDNS which can solve the pure native app's dns lookup problem, as it can send a http request by the ip(fetched from the HttpDNS) not domain, and set the domain of http header by hand. However in webview, we can't do that.
So is there a way to solve the dns problems in webview? Thank you (We found that we can set a proxy in app which can solve the dns lookup problems but this method is not so novel. ).

You can either:
Detect the page load failure and retry
Provide a custom delegate that intercepts each request, performs the lookup, loads the content using NSURLConnection/NSURLSession, and then injects the content into the web view.
Neither approach is perfect, of course, as both are effective only if the user is loading a page that replaces the current page in the web view (as opposed to random XMLHTTPRequest calls).
And then, there's always:
Swizzle NSURLConnection and NSURLSession, rewriting the request objects based on the result of your own lookup code, and overwriting the Host header field.
Although this does have the advantage of working even for XHR, I would tend to recommend against this approach for publicly distributed apps, though, for three reasons:
Apple says not to touch the Host header field, which means future OS updates could break the behavior (assuming it even works).
It is really easy to break things if you swizzle those classes incorrectly.
It will change the way those classes behave for every request coming from your app, not just requests made by the web view.
Of course, you could avoid the first problem by adding libcurl and using that to perform the actual request, but then you're getting into seriously scary compatibility territory. :-)
You might be better off trying to find out why the DNS lookup is failing. Is it being blocked locally by an abusive ISP or government? Can you add VPN technology to your app so that requests for your URL (and DNS lookups) get routed through a tunnel?

Related

Android: How to capture App's Network Traffic Programmatically?

I'm currently working on a library that enables QA or Developers debug network traffic in their app, we currently use OKHttp and I know how to create an interceptor and dispatch all request data to the lib. such that Developers or QA can view such data (Payload/URL/Size/Response Codes/Duration...etc), however I want to create a more generic solution that listens to HTTP traffic or even TCP traffic then take it from there, however I couldn't find a starting point, I know that this is possible since Firebase Performance is doing it, but still I couldn't find an API or anyway to listen to such traffic.
I hope that someone from Google's Firebase Performance Team shares some info about how they do it if it's not a trade-secret :)
I came across this solution: https://github.com/cyruliu/Sensitive_API_Monitor/blob/master/app/src/main/java/com/android/reverse/apimonitor/NetWorkHook.java
However it looks kinda bad with reflection, I hope to find a better way.
The short answer: It's not possible without proxying the whole device.
For OkHttp3 specifically I wrote a lib here: https://github.com/shehabic/sherlock that implements an interceptor that creates a new session every time your open your app and captures network requests, you can also have multiple session, it adds a floating icon that helps you access sessions and requests' history as well as some export capabilities, additionally it adds a secondary launcher icon that you can use to access the captures requests without interrupting the app's process.
Regarding Firebase Performance, all the magic is actually in the Firebase-Perf Gradle plugin; to simplify it, it scans through the project's code and replaces direct calls to OkHttpClient to be be proxied through their own FirebaseOkHttpClient and from there they get all the details even for https request as they become the http client.
I hope that this saves someone some time in the future.

Given a HTTP request, is it possible to see which application originated it?

Let's assume a scenario where all the network traffic is redirected through a local proxy, running on an Android device.
Within the proxy, is it possible to see which application (in terms of package name, application name, ..) originated that particular network call?
EDIT: apologies, I was short on details here. I'm referring to the HTTP protocol, hence a network call is just an HTTP request (either GET or POST) to some URL.
Depends on what info the app sends on the packet. If you're asking if network packets (btw you didn't specify which protocol you're referring to) have by default info about the app that sent it, then the answer is no.
But you can study the packets of a given set of apps, store this info in the proxy and then you can detect, given enough packets, the source app. Of course this won't yield info about apps you don't know.
EDIT: if it's an HTTP request, then usually the HTTP header includes information about the app that originates this request (e.g. browser version).
I found a way to do it. Bit of a workaround, actually, but seems to be working flawlessly.
I wrote a simple Android library to do so, if anyone wants to check it out. It is based on the fact that each socket is mapped as an entry on a file, called /proc/net/tcp (or /proc/net/tcp6 for IPv6-based connections).
This means that, for each entry, we can read its port and its associated PID.
Basically, the main method of the library performs the following steps:
Receives a Socket object or the associated port (Socket.getPort())
Parses the /proc/net/tcp (or /proc/net/tcp6) file, it looks for an entry with the given port
If an entry is found, the method extracts the PID from it
By calling the Android PackageManager.getPackagesFromPid() method with the newly found PID, we can obtain the unique information about the source application, such as package name and application version
The performances are quite good, since the /tcp* file is usually no longer than 50 entries.

Extending an existing Web application with Android app

I have a new project involving the build of an Android app for a website of a hiking club. The website has a login functionality after which the user can browse through available hikes, subscribe to a hike, view the other subscribers, contact the organizer etc.
The original site is based on a MySQL database with a front end of .asp pages. Most data is passed through the pages as GET parameters on the query string.
New to Android development, some things really puzzle me, even after reading several tutorials. I am thinking towards an architecture baes on REST webservices but there a several obstacles to overcome and chooses to be made.
Apart from using REST, some other options are available:
Call the original .asp pages from the app instead of building a dedicated Web service. This leaves me with much less code to write, the original business logic (queries e.a.) as well as the login system can be used (with the "remember me" functionality based on cookies). Downside is that the (X)HTML code in the response needs to be parsed to show in the app GUI, where the majority of the response code is useless ballast code. Also, it does not feel very good from an archtitectorial point of view.
Using a SOAP based webservice. I am totally unfamiliar with SOAP and it appears to be much too heavyweight for a mobile device.
Using REST services. I am leaning towards this option, and have made
some already working services using the SLIM framework. But there
are some problems. First, REST is stateless by definition and does
not seem to support sessions. But the "Remember me" option is
required for the app after login in for the first time, the user
needs not to login again unless he explicitly logs out.
But how can we achieve that?
First option is to designing some completely client-site login/logout system which saves the credentials locally until the user logs out. And sending the credentials with each request to the Web service as POST parameters, or somehow in the HTTP Authorization request header, though I am not familiar with that.
Second option is to deviate a bit from RESt principles and use a session mechanism anyway. After sending the credentials to the web service, a cookie is created and send to the client app. The dartabase cannot be extended so there is no option to save a token in the user table. Maybe the usernae/password can be encrypted and send as a cookie to the app, and decrypted at each subsequent request?
I am a bit lost in this, and look forward to serious suggestions!
I believe that from a long term perspective, it is important that you lean towards REST Interfaces. While JSoup and/or WebView approaches will definitely work, it is important to have the flexibility to redefine/design the mobile application in ways that are completely agnostic of the Server side. REST will help you there and you do not need to play catch up with the Server side, everytime they change the HTML pages, etc.
Going REST will also help in future with writing additional mobile applications and even on different platforms like iOS, if your roadmap contains that.
You can use jsoup to parse the html pages from your Android app and reorganize the information of the web page, this option will gives you ability to quickly develop an App, later you may think on add REST interfaces to your web site and populate data in json.
You can also use WebView to laod your web pages if you don't want to parse html pages.
I suggest you using REST architecture as you said. You can use a rest client library for Android as RESTDroid, take a look to the guide because there is a implementation example with special header needed for the particular web service used (Parse.com in this case).

Android How to hide server url for security in code?

My application need to communicate frequently.
So there are many url: http://abc.php
The question is even if I use proguard, is it possible for people to get the url and hack in the system.
What should I do so that it can hide the link and make my system more secure.
You can't. Any one can get you app and use sniffers to check where your application sends request. You should provide good security on server.
Any URL or web service you are sending them to should only be for uses such as JSON/XML requests. There shouldn't be anything that critical in a wide open base URL. If there is then you have problems to begin with. Plus you may try to hide your URL, but with simple networking tools attached to the application it would be very easy to sniff the IP address and do other public functions to look-up the url. Any URL you have would be public, thus you need to take security measures on another end.

How to save/load data Online(Store data with AJAX and JSON) and Offline (locally)

I need help figuring out the best, cross-browser compatible way to "SAVE" user input and STORE them locally(offline mod) AND on a server(online). Program will be used by Android and iOS.
I want to know the best way to track user progress while the device is online OR offline.
Hello I have been researching AJAX, JSON, XMLHttpRequest, REST, Java, and HTML5 (specifically, localStorage).
The scenario: (Read a book online/offline, save page progress)
A user logs in to a Web Service and the Web Service allows the user to download an "html webpage book" (view with HTML5 browser).
After every page turn, a REST API uses a GET request to post the Progress data to a Web Server. Simultaneously, a JSON string is created and saved in a file on the server. (let's say "ProgressData.txt")
In the background, a separate "copy" of ProgressData.txt is saved LOCALLY on the mobile device. The user then leaves the internet connection and continues to read the HTML Book.
When the user regains connectivity, the ProgressData.txt is uploaded to the server using a REST API where it will update the old server file with the NEW .txt file with all of the user ProgressData.
Possible solutions:
HTML5 localStorage solution looks good. jQuery even simplifies it:
http://plugins.jquery.com/project/html5Storage
Straight Javascript looks good for Server-Side storage, however it doesn't have access to a mobile device's physical hard-drive, thus preventing any kind of offline saving.
Java applets look possible. Plus not sure how Java runs with Android/iOS.
I don't want to have to run a localhost(PHP/Apache/Python) from a mobiledevice every time the user goes offline, however that may be where the solution lies. I did stumble on this powerful tool: http://couchdb.apache.org/
Question:
I need to know the best way to track user progress while the device is online OR offline. What is the best way to do this?
I stumbled across store.js the other day which might help solve the cross browser local storage. It was from this article about local storage.
I think your best option for tracking online/offline is to ping the server via an AJAX call when the page is turned. Always try and update the server on a page turn, but if it fails, handle the failure and store the progress locally. Each page turn will either amend the locally stored progress file or if connection is restored then simply update the server with the progress.
The issue I am thinking might occur is if a book is finished offline then there are no more clicks that would trigger the syncing, regardless of a restored connection. You may want to think about a manual sync link/button at the end of a book. Or maybe have a manual sync available at all times anyway? Give some control to the users and describe the whole offline/online reading scenario. You might find that it is easier to just let the users do the work… if they don't sync then it's their problem!
Here are 2 screencasts what will help you with your problem.
They are in Ruby on Rails but maybe you can get the idea. It is using the html5 cache manifest.
Hope it will help you!
http://railscasts.com/episodes/247-offline-apps-part-1
http://railscasts.com/episodes/248-offline-apps-part-2
some more resources (sorry i dont have experiences myself with html5 cache manifest)
http://diveintohtml5.ep.io/offline.html
http://developer.apple.com/library/safari/#documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html
I'd suggest just using a cookie to store the current state. That way it is automatically sent to your server with every user request (so no need to build out a custom server-side API for receiving the state after a lost connection, and no need to have any custom client-side code for sending the data to the server), and still updateable even if the user has lost Internet connectivity. Also it doesn't rely on HTML5 features, so you don't need to restrict people to HTML5-capable browsers.
In any case, the best way to handle storing the current state would be to have a simple onclick handler on your "next page" link (or button, or whatever it is) that calls a function and sets the cookie value to whatever the current position is. Note that because the state is always available client-side, and sent to the server on every request, there is no need to maintain any explicit copy of the state server-side, unless you want to be able to remember the user's place even when they manually delete their cookies (which is overkill in my opinion).
You may want to look at the W3C Example Code for setting/getting cookie values in JavaScript.
Also, here's a website that demonstrates functionality similar to what you want to build. It uses cookies to keep track of a user's place when reading various webcomics. Pretty much the same as what it sounds like you want, except with comics instead of books.
It would be wise to track the progress in both a server side database and in the client's local storage if a constant internet connection is not necessary.
Evercookie is a controversial javascript api that aims to provide local storage using any means available including standard cookies, Flash shared object, Silverlight, browser history and HTML 5 storage. Data should persist when the user is offline and when the connection is restored, sync the cookie and database with whichever data has greater page number for the given book. Droid has Flash and the Flash shared object data is a "cookie" available to both desktop and web-based apps.
With great power comes great responsibility:
http://samy.pl/evercookie/

Categories

Resources