Android – Logging into a website programatically without HTTP authentication
A major problem I ran into when I was working on my first Android app, NetClassroom (you can read more about this in the Projects section), was that the login site I was adapting into an Android app did not allow me to post the login credentials to the server and wait for a response. If I couldn’t do this, then the app would be impossible to make. Even if I was able to get my own school to allow authentication like this, the app would still be incompatible with the 100+ schools I was planning on including as it seems the default settings prevent authentication.
Looking around on StackOverflow yielded few leads, mainly people suggesting a WebView to display the page, but the whole purpose was to escape the poor mobile experience of the actual site. Like solving any other programming problem, when I actually thought of a solution, it was unbelievably simple.
Taking the login information is easy, so I’ll assume you already know how to do that. From there, you can just send the credentials to a activity with a WebView, which allows you to load in JavaScript. What does this mean? It means you can literally tell the WebView: “Put the username and password in the appropriate inputs, and click the login button.” So lets go do that.
First you need to declare your instance variables. As mentioned earlier, we’re going to be working with a WebView, so declare that. I don’t know how you’re getting your username and passwords. For me, I included them in a bundle when I started this login activity, but that’s just my case.
WebView mWebView; int countLoad = 0; String URL = "www.example.com"; //Your login form String username; String password;
Because this is done within a regular activity, you have to put a WebView declaration somewhere in the XML layout you are using for this activity. Mine’s id is just ‘webview’, as seen in the first line below. About View.GONE: I did this a while ago, but I think I ran into some problems making it an AsyncTask, which is why I just did this whole login process in its own activity. I don’t want to show the WebView, so I set the visibility to View.GONE so it would be black while it the app logs in. I also put a ProgressDialog over it, but that’s just me.
You also need to enable JavaScript so we can load JavaScript into the WebView. That line (3) is pretty self-explanatory. The last line injects the jsInterfaceObj object into the WebView context, which allows the object’s public methods to be accessed from JavaScript. It’s alright if you don’t understand this. Basically, the last two lines allow us to inject JavaScript and adapt a JavaScript interface that sort of connects the JavaScript to this.
mWebView = (WebView) findViewById(R.id.webview); mWebView.setVisibility(View.GONE); //You can delete this line while you are testing just to see how it works. mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new jsInterface(), "HTMLOUT");
You also need to define the aforementioned jsInterface class so that we have we can tell the interface what to do with the HTML we’re going to eventually get. So define the following class somewhere. I’m just adding the HTML as an extra which you can extract in the next class, but you can do whatever you want with the HTML that we’re getting.
class jsInterface{
public void showHTML(String html){
String test = "";
Intent openNewActivity = new Intent("android.intent.action.yourintent");
openNewActivity.putExtra("HTML", html);
startActivity(openNewActivity);
}
}
Okay, now it gets a little trickier. We need to add a WebViewClient, which basically allows us to tell the WebView what to do. In this case, we’re telling the WebView what to do when loadUrl() completes, and we do this by defining onPageFinished().
Remember the loadCount variable we initialized before? Here’s where that comes into play. After we initially use loadUrl() to load the login page (which we haven’t done yet), it refers to onPageFinished() and sees that we want to run this secondary loadUr() that loads in JavaScript. We are using the loadCount to prevent a never ending loop. After the login page URL is initially loaded, we want it to load the JavaScript (when loadCount is 0). When this secondary loadUrl is finished, we want to grab the HTML of the page (when loadCount is 1). We run the interface’s showHTML function with the HTML (which is returned from pretty simple JavaScript) as a parameter. If you remember, I just bundled it into a new activity, but you can do whatever you want with it.
Also note the JavaScript getElementById function: remember to change the input ids to match that of the page you’re working on. If, for some odd reason, you aren’t already using FireBug or something equivalent, I highly recommend you download something, as it will come in handy in situations like this.
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
if (loadCount == 0) {
mWebView.loadUrl(
"javascript:document.getElementById('sid').value = '" + username + "';"+
"javascript:document.getElementById('pin').value = '" + password + "';"+
"javascript:document.getElementById('btnLogin').click();"
);
loadCount++;
} else if (loadCount == 1) {
mWebView.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
loadCount++;
}
}
});
Finally, you’re in. If you run the following code, the showHTML function will run and your activity will open with the returned HTML as an extra. Also keep in mind the fact that this HTML is of the page that the user is sent to when he logs in with valid login credentials.
mWebView.loadUrl(URL);
That’s it. It’s probably very simple for anyone with considerable experience, but as a beginner I had a lot of problems trying to get this to work, so I thought an in-depth tutorial like this would help someone. Please let me know what you think. If you need some help, don’t hesitate to comment below or send me an email and I’ll do my best to try and help you out. Thanks for reading!


