Ok, luckily Bluehost has a cpanel option which allows you to easily do so. Now, I just need to figure out the code to provide the username and password programmatically. I have found a nice little url which has some canned code for doing so:
http://www.exampledepot.com/egs/java.net/Auth.html
Here's the code:
// Install the custom authenticator
Authenticator.setDefault(new MyAuthenticator());
// Access the page
try {
// Create a URL for the desired page
URL url = new URL("http://hostname:80/index.html");
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
// str is one line of text; readLine() strips the newline character(s)
}
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
public class MyAuthenticator extends Authenticator {
// This method is called when a password-protected URL is accessed
protected PasswordAuthentication getPasswordAuthentication() {
// Get information about the request
String promptString = getRequestingPrompt();
String hostname = getRequestingHost();
InetAddress ipaddr = getRequestingSite();
int port = getRequestingPort();
// Get the username from the user...
String username = "myusername";
// Get the password from the user...
String password = "mypassword";
// Return the information
return new PasswordAuthentication(username, password.toCharArray());
}
}
Ok, wouldn't it be sweet if this went through with no time-consuming problems?
It's a little confusing - what's this "Authenticator" that the public class "MyAuthenticator" is extending?
Let's google it...
http://developer.android.com/reference/java/net/Authenticator.html
Ok, it's an abstract class, so that means it's just hanging around to be implemented. But, how does it get called back to?
Class Overview
An implementation of this class is able to obtain authentication information for a connection in several ways. For this purpose it has to set the default authenticator which extends Authenticator by setDefault(Authenticator a). Then it should override getPasswordAuthentication() which dictates how the authentication info is obtained. Usually, it prompts the user for the required input.
Ok, that's exactly what it's doing, but it's providing the password. It must be some how connected to creation of the URL.
Ok, let's just add the class to the project, first. Ok, that's done, with the correct name and passwordk. Now just add this before creating the url:
// Install the custom authenticator
Authenticator.setDefault(new MyAuthenticator());
Ok. Let's see if it works!
Oh, yeah, first I have to remove the data directory, which can't be seen by adb shell since it begins with a "." so let's try this:
# rm -r ./.com*
Ok, it look like that worked. Double check in astro, which does see it...yep, it's gone.
Ok, let's run the install...
Well, I got rid of the media files, but somehow the data directory is still there. Rats.
logcat shows it went to the download, but just nothing happened. It just completed - no exceptions thrown, nothing. But the file didn't get downloaded.
Let's see if this gets called:
Log.d(TAG, ">>>>>>>>>>>>>>>>>> getPasswordAuthentication() called! <<<<<<<<<<<");
Nope, it's not called. Pffft.
Let's look at the docs again:
public static void setDefault (Authenticator a)
Since: API Level 1
Sets a as the default authenticator. It will be called whenever the realm that the URL is pointing to requires authorization. If there is a security manager set then the caller must have the appropriate NetPermission.
Parameters
a authenticator which has to be set as default.
Throws
SecurityException if a security manager denies the password authentication permission.
Well, I don't *think* I have a security manager.
This post looks helpful:
http://stackoverflow.com/questions/1968416/how-to-do-http-authentication-in-android
It gives a more compact form, like this:
Authenticator.setDefault(new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("myuser","mypass".toCharArray());
}});
HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
c.setUseCaches(false);
c.connect();
But I don't see any substantive difference between that and the one I'm using except the setUsesCache method.
But, he also give another tip to try:
c.setRequestProperty("Authorization", "basic " +
Base64.encode("myuser:mypass".getBytes()), Base64.DEFAULT);
Let's try it.
Nope. I wonder what the problem is? It's just not making that call. Does it make any difference if I pull the authentication code?
I doubt it, but just be sure.
Nope. Same thing.
Let's check the source code...
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/net/Authenticator.java#Authenticator
Ah so that's how it's gets set to the url:
Sets the authenticator that will be used by the networking code when a proxy or an HTTP server asks for authentication.
Sometimes just glancing at the source is worth it.
Still, that doesn't solve my problem. What if I access the directory from the Android device browser...ah. I see. I wasn't logged into the network (I only use wireless lans to access the net on the phone). Ok. let's comment back in the security code.
Ah, yes. Sweeter than sweet. It's loading.
Ok, let's put the name and password into strings for an extra layer of protection.
Ok, I'm having some trouble with this...
D/DownloadAudioData( 4009): enter download from url
W/ResourceType( 4009): getEntry failing because entryIndex 25 is beyond type entryCount 25
W/ResourceType( 4009): Failure getting entry for 0x7f080019 (t=7 e=25) in package 0 (error -2147483647)
W/dalvikvm( 4009): threadid=10: thread exiting with uncaught exception (group=0x40015560)
I/ActivityManager( 101): Displayed com.jlptquiz.app/.StartActivity: +3s423ms
E/AndroidRuntime( 4009): FATAL EXCEPTION: AsyncTask #1
E/AndroidRuntime( 4009): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime( 4009): at android.os.AsyncTask$3.done(AsyncTask.java:200)
E
E/AndroidRuntime( 4009): at java.lang.Thread.run(Thread.java:1019)
E/AndroidRuntime( 4009): Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7f080019
E/AndroidRuntime( 4009): at android.content.res.Resources.getText(Resources.java:201)
E/AndroidRuntime( 4009): at android.content.res.Resources.getString(Resources.java:254)
E/AndroidRuntime( 4009): at android.content.Context.getString(Context.java:183)
E/AndroidRuntime( 4009): at com.jlptquiz.app.DownloadAudioData$DownloadFilesTask.downloadFromUrl(DownloadAudioData.java:212)
E
Ok, it's just not finding the resource string. Let's double check the name...
What if I do a clean?
There we go. I actually was trying to speed through that, thinking it would be easy and not bothering to look at the logcat, or only briefly. Remember - never, ever, rush. Just don't. It never works.
Ok. That's a wrap for today. Security is in there - just basic - but, I just don't want to muck around with ssh and certicates right now. I have a couple of layers in there at least. A password-protected directory, and moving the values out of the code. Cool.
No comments:
Post a Comment