com.mediaexplorer.remote.MexRemoteActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.mediaexplorer.remote.MexRemoteActivity.java

Source

/*
 * Mex android remote - a wraper and discovery tool for the mex web remote
 *
 * Copyright  2011 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses>
 */

package com.mediaexplorer.remote;

import java.io.IOException;

import android.app.Activity;
import android.os.Bundle;

/* Jmdns licenced under Apache 2 please see NOTICE.TEXT in libs */
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceListener;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;

import android.widget.TextView;
import android.app.ProgressDialog;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.HttpAuthHandler;
import android.webkit.WebViewDatabase;

import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.text.method.PasswordTransformationMethod;
import android.view.ViewGroup.LayoutParams;

import android.widget.Toast;

import android.util.Log;

import org.apache.http.HttpResponse;
import org.apache.http.client.*;
import org.apache.http.auth.*;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.CredentialsProvider;

public class MexRemoteActivity extends Activity {
    /* Called when the activity is first created. */

    private android.net.wifi.WifiManager.MulticastLock lock;
    private android.os.Handler handler = new android.os.Handler();
    private JmDNS jmdns = null;
    private ServiceListener listener = null;
    private ProgressDialog dialog;
    private TextView text_view;
    private WebView web_view;
    private String target_host;
    private int target_port;
    private String dbg;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        this.setTitle(R.string.app_name);
        dbg = "MexWebremote";

        text_view = (TextView) findViewById(R.id.text);

        web_view = (WebView) findViewById(R.id.link_view);
        web_view.getSettings().setJavaScriptEnabled(true);/*
                                                          /* Future: setOverScrollMode is API level >8
                                                          * web_view.setOverScrollMode (OVER_SCROLL_NEVER);
                                                          */

        web_view.setBackgroundColor(0);

        web_view.setWebViewClient(new WebViewClient() {
            /* for some reason we only get critical errors so an auth error
             * is not handled here which is why there is some crack that test
             * the connection with a special httpclient
             */
            @Override
            public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler,
                    final String host, final String realm) {
                String[] userpass = new String[2];

                userpass = view.getHttpAuthUsernamePassword(host, realm);

                HttpResponse response = null;
                HttpGet httpget;
                DefaultHttpClient httpclient;
                String target_host;
                int target_port;

                target_host = MexRemoteActivity.this.target_host;
                target_port = MexRemoteActivity.this.target_port;

                /* We may get null from getHttpAuthUsernamePassword which will
                 * break the setCredentials so junk used instead to keep
                 * it happy.
                 */

                Log.d(dbg, "using the set httpauth, testing auth using client");
                try {
                    if (userpass == null) {
                        userpass = new String[2];
                        userpass[0] = "none";
                        userpass[1] = "none";
                    }
                } catch (Exception e) {
                    userpass = new String[2];
                    userpass[0] = "none";
                    userpass[1] = "none";
                }

                /* Log.d ("debug",
                 *  "trying: GET http://"+userpass[0]+":"+userpass[1]+"@"+target_host+":"+target_port+"/");
                 */
                /* We're going to test the authentication credentials that we
                 * have before using them so that we can act on the response.
                 */

                httpclient = new DefaultHttpClient();

                httpget = new HttpGet("http://" + target_host + ":" + target_port + "/");

                httpclient.getCredentialsProvider().setCredentials(new AuthScope(target_host, target_port),
                        new UsernamePasswordCredentials(userpass[0], userpass[1]));

                try {
                    response = httpclient.execute(httpget);
                } catch (IOException e) {
                    Log.d(dbg, "Problem executing the http get");
                    e.printStackTrace();
                }

                Log.d(dbg, "HTTP reponse:" + Integer.toString(response.getStatusLine().getStatusCode()));
                if (response.getStatusLine().getStatusCode() == 401) {
                    /* We got Authentication failed (401) so ask user for u/p */

                    /* login dialog box */
                    final AlertDialog.Builder logindialog;
                    final EditText user;
                    final EditText pass;

                    LinearLayout layout;
                    LayoutParams params;

                    TextView label_username;
                    TextView label_password;

                    logindialog = new AlertDialog.Builder(MexRemoteActivity.this);

                    logindialog.setTitle("Mex Webremote login");

                    user = new EditText(MexRemoteActivity.this);
                    pass = new EditText(MexRemoteActivity.this);

                    layout = new LinearLayout(MexRemoteActivity.this);

                    pass.setTransformationMethod(new PasswordTransformationMethod());

                    layout.setOrientation(LinearLayout.VERTICAL);

                    params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

                    layout.setLayoutParams(params);
                    user.setLayoutParams(params);
                    pass.setLayoutParams(params);

                    label_username = new TextView(MexRemoteActivity.this);
                    label_password = new TextView(MexRemoteActivity.this);

                    label_username.setText("Username:");
                    label_password.setText("Password:");

                    layout.addView(label_username);
                    layout.addView(user);
                    layout.addView(label_password);
                    layout.addView(pass);
                    logindialog.setView(layout);

                    logindialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            dialog.cancel();
                        }
                    });

                    logindialog.setPositiveButton("Login", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            String uvalue = user.getText().toString().trim();
                            String pvalue = pass.getText().toString().trim();
                            view.setHttpAuthUsernamePassword(host, realm, uvalue, pvalue);

                            handler.proceed(uvalue, pvalue);
                        }
                    });
                    logindialog.show();
                    /* End login dialog box */
                } else /* We didn't get a 401 */
                {
                    handler.proceed(userpass[0], userpass[1]);
                }
            } /* End onReceivedHttpAuthRequest */
        }); /* End Override */

        /* Run mdns to check for service in a "runnable" (async) */
        handler.post(new Runnable() {
            public void run() {
                startMdns();
            }
        });

        dialog = ProgressDialog.show(MexRemoteActivity.this, "", "Searching...", true);

        /* Let's put something in the webview while we're waiting */
        String summary = "<html><head><style>body { background-color: #000000; color: #ffffff; }></style></head><body><p>Searching for the media explorer webservice</p><p>More infomation on <a href=\"http://media-explorer.github.com\" >Media Explorer's home page</a></p></body></html>";
        web_view.loadData(summary, "text/html", "utf-8");

    } /* end OnCreate */

    private void startMdns() {
        android.net.wifi.WifiManager wifi;

        wifi = (android.net.wifi.WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);

        /* We need to specifically switch on get multicast packets as usually
         * they're disregarded, turn off soon as possible due to battery drain
         */

        lock = wifi.createMulticastLock("mexremote");
        lock.setReferenceCounted(true);
        lock.acquire();

        try {
            jmdns = JmDNS.create();
            jmdns.addServiceListener("_http._tcp.local.", listener = new ServiceListener() {
                @Override
                public void serviceResolved(ServiceEvent event) {
                    if (event.getName().startsWith("Mex Webremote")) {
                        dialog.dismiss();
                        /* TODO handle multiple mex web remotes and give an option
                         * to select a particular one.
                         */
                        MexRemoteActivity.this.target_host = event.getInfo().getInetAddress().getHostAddress();
                        MexRemoteActivity.this.target_port = event.getInfo().getPort();

                        remoteFound("http://" + MexRemoteActivity.this.target_host + ":"
                                + MexRemoteActivity.this.target_port + "/");

                        /* release asap to save battery */
                        lock.release();
                    }
                }

                @Override
                public void serviceRemoved(ServiceEvent event) {
                    dialog.show();
                    jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
                }

                @Override
                public void serviceAdded(ServiceEvent event) {
                    /* Ask for the new item to be resolved */
                    jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
                }

            });
        } catch (IOException exception) {
            exception.printStackTrace();
            return;
        }
    }

    private void remoteFound(final String response) {
        handler.post(new Runnable() {
            public void run() {
                /* todo build list of mex targets and add selector */
                Log.d(dbg, "Response: " + response + "\ntarget host" + target_host + "\n port:" + target_port);
                text_view.setText("Media explorer remote:" + response);
                web_view.loadUrl("http://" + target_host + ":" + target_port + "/");
            }
        });

        if (jmdns != null) {
            if (listener != null) {
                jmdns.removeServiceListener("_http._tcp.local.", listener);
                listener = null;
            }
            jmdns = null;
        }
    }

    @Override
    protected void onStop() {
        Log.d(dbg, "Stop");
        super.onStop();
        System.exit(0);
    }

}