jp.maju.wifiserver.client.ClientActivity.java Source code

Java tutorial

Introduction

Here is the source code for jp.maju.wifiserver.client.ClientActivity.java

Source

package jp.maju.wifiserver.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

import jp.maju.wifidetecter.reciever.ConnectionObserver;
import jp.maju.wifidetecter.reciever.ConnectionObserver.OnStateListener;
import jp.maju.wifiserver.CustomWebView;
import jp.maju.wifiserver.CustomWebView.OnClickLinkListener;
import jp.maju.wifiserver.GateActivity;
import jp.maju.wifiserver.R;
import jp.maju.wifiserver.SocketInfo;
import jp.maju.wifiserver.twitter.TweetTask;
import jp.maju.wifiserver.twitter.TweetTask.OnTweetResultListener;
import jp.maju.wifiserver.twitter.TwitterUtils;
import jp.maju.wifiserver.util.CommonUtil;
import jp.maju.wifiserver.util.Logger;
import jp.maju.wifiserver.util.PreferenceUtil;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.URLCodec;

import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

/*
 * Copyright {2014} {Matsuda Jumpei}
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
public class ClientActivity extends ActionBarActivity
        implements OnStateListener, OnClickLinkListener, OnTweetResultListener {
    private static final String TAG = ClientActivity.class.getSimpleName();
    public static final String KEY_SOCKET_INFO = "keySocketInfo";

    private static final int WHAT_SHOWING_TOAST = 101;
    private static final int WHAT_LOAD_AS_HTML_2_WEBVIEW = 102;

    private volatile Socket mSocket;
    private PrintWriter serverOutWriter;
    private ConnectionObserver mClientObserver;
    private MessageHandler mMessageHandler;
    private volatile Thread clientThread;
    private CustomWebView mWebView;
    private SocketInfo mSocketInfo;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            if (getIntent() == null) {
                finish();
                return;
            }

            Serializable s = getIntent().getSerializableExtra(KEY_SOCKET_INFO);

            if (s == null || !(s instanceof SocketInfo)) {
                finish();
                return;
            }

            mSocketInfo = (SocketInfo) s;
        } else {
            mSocketInfo = (SocketInfo) savedInstanceState.getSerializable(KEY_SOCKET_INFO);
        }

        //        PreferenceUtil.setAnchor(getApplication(), mSocketInfo.getKind());

        CommonUtil.stopService(this, ClientService.class);

        setContentView(R.layout.activity_client);

        mWebView = (CustomWebView) findViewById(R.id.wv_client_content);
        mWebView.setOnClickLinkListener(this);

        mClientObserver = new ConnectionObserver();
        mClientObserver.setOnStateListener(this);

        mMessageHandler = new MessageHandler(this);

        registerReceiver(mClientObserver, CommonUtil.getNewIntentFilterWillBeRecieved());

        if (mSocketInfo != null) {
            Logger.d(TAG, mSocketInfo.toString());

            doConnect2Server();
        } else {
            finish();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(KEY_SOCKET_INFO, mSocketInfo);
    }

    @Override
    protected void onDestroy() {
        if (mClientObserver != null) {
            unregisterReceiver(mClientObserver);
            mClientObserver = null;
        }

        if (mWebView != null) {
            mWebView.destroy();
            mWebView = null;
        }

        end();

        CommonUtil.startService(this, ClientService.class);

        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        if (mClientObserver != null) {
            unregisterReceiver(mClientObserver);
            mClientObserver = null;
        }

        if (mWebView != null) {
            mWebView.destroy();
            mWebView = null;
        }

        end();

        CommonUtil.startService(this, ClientService.class);

        super.onBackPressed();
    }

    private void loadHtmlString(String str) {
        mWebView.loadData(str, "text/html; charset=utf-8", "utf-8");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.client, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_client_connect:
            doConnect2Server();
            break;
        case R.id.menu_client_disconnect:
            onDisabling();
            break;
        case android.R.id.home:
            startActivity(new Intent(this, GateActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
            finish();
            break;
        }

        return true;
    }

    private void doConnect2Server() {
        if (clientThread == null) {
            clientThread = new Thread(new ClientWorker());
            clientThread.start();
        }
    }

    private void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    private void sendMessage(String msg) {
        if (mSocket != null && mSocket.isConnected() && !mSocket.isClosed()) {
            serverOutWriter.println(msg);
        }
    }

    private class ClientWorker implements Runnable {
        private boolean connect2Server() {
            int retryCount = 0;
            while (mSocket == null && retryCount < 10) {
                InetAddress serverAddr;

                try {
                    serverAddr = InetAddress.getByName(mSocketInfo.getHost());
                    // ProxyWrapper pWrapper =
                    // ProxyWrapper.getRegisteredProxy(getApplication(),
                    // CommonUtil.getCurrentSSID(getApplicationContext()));
                    // if (pWrapper != null) {
                    // Proxy proxy = new Proxy(Proxy.Type.SOCKS, new
                    // InetSocketAddress(pWrapper.host, pWrapper.port));
                    // mSocket = new Socket(proxy);
                    // InetSocketAddress dest = new
                    // InetSocketAddress(serverAddr, SERVER_PORT);
                    // mSocket.connect(dest);
                    // } else {
                    mSocket = new Socket(serverAddr, mSocketInfo.getPort());
                    // }

                    serverOutWriter = new PrintWriter(
                            new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
                } catch (UnknownHostException e) {
                    Logger.e(TAG, e);
                } catch (IOException e) {
                    Logger.e(TAG, e);
                }

                retryCount++;
            }

            if (mSocket != null && retryCount <= 10) {
                Logger.d(TAG, "Login successful.");
                return true;
            } else {
                Logger.d(TAG, "Login failed.");
                return false;
            }
        }

        private void listen2ServerMessage() {
            try {
                BufferedReader iReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));

                while (mSocket != null && !mSocket.isClosed() && iReader != null
                        && !Thread.currentThread().isInterrupted()) {
                    try {
                        String read = iReader.readLine();

                        if (!TextUtils.isEmpty(read)) {
                            loadHtmlString(read);
                        }
                    } catch (IOException e) {
                        Logger.e(TAG, e);
                        iReader = null;
                    }
                }
            } catch (IOException e) {
                Logger.e(TAG, e);
            }
        }

        private void loadHtmlString(String str) {
            Message msg = new Message();
            msg.what = WHAT_LOAD_AS_HTML_2_WEBVIEW;
            msg.obj = str;

            mMessageHandler.sendMessage(msg);
        }

        private void sendMessageForRendering() {
            sendMessage(PreferenceUtil.getUUID(getApplication()));
        }

        @Override
        public void run() {
            if (!connect2Server()) {
                return;
            }

            sendMessageForRendering();

            listen2ServerMessage();
        }
    }

    private static class MessageHandler extends Handler {
        private WeakReference<ClientActivity> wRef;

        public MessageHandler(ClientActivity service) {
            wRef = new WeakReference<ClientActivity>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            ClientActivity ca = wRef.get();

            if (ca == null) {
                return;
            }

            switch (msg.what) {
            case WHAT_SHOWING_TOAST:
                ca.showToast((String) msg.obj);
                break;
            case WHAT_LOAD_AS_HTML_2_WEBVIEW:
                ca.loadHtmlString((String) msg.obj);
            }

            super.handleMessage(msg);
        }
    }

    @Override
    public void onDisabled() {
        end();
    }

    @Override
    public void onDisabling() {

    }

    private void end() {
        if (serverOutWriter != null) {
            serverOutWriter.close();
            serverOutWriter = null;
        }

        if (clientThread != null) {
            clientThread.interrupt();
            clientThread = null;
        }

        if (mSocket != null) {
            try {
                mSocket.shutdownInput();
                mSocket.shutdownOutput();
                mSocket.close();
            } catch (IOException e) {
                Logger.e(TAG, e);
            }
            mSocket = null;
        }
    }

    @Override
    public void onEnabling() {
        // onDisabling();
    }

    @Override
    public void onEnabled() {
    }

    @Override
    public void onUnknownState() {
        // onDisabling();
    }

    @Override
    public void onConnected(NetworkInfo info) {

    }

    @Override
    public void onConnecting(NetworkInfo info) {
        // onDisabling();
    }

    @Override
    public void onDisconnectingOrOther(NetworkInfo info) {
        end();
    }

    @Override
    public void onClickLink(String url) {
        if (url.startsWith(CustomWebView.URL_RESULT_REGISTER) || url.startsWith(CustomWebView.URL_RESULT_LOGIN)) {
            url = url + "&uuid=" + PreferenceUtil.getUUID(getApplication());
        }

        if (url.startsWith(CustomWebView.URL_TWEET)) {
            String query = url.substring(CustomWebView.URL_TWEET.length());
            String[] params = query.split("&");
            String kind = params[0].substring("name=".length());
            String msg = params[1].substring("href=".length());
            String login = params[2].substring("login=".length());
            boolean isLogin = login.equals("true");

            Twitter twitter = TwitterUtils.getRegisteredTwitterInstance(getApplication(), false);

            try {
                URLCodec codec = new URLCodec();
                kind = codec.decode(kind, "UTF-8");
                kind = kind.substring(0, kind.length() - 2).toString();

                String storedKind = PreferenceUtil.getAnchor(getApplication());

                if (storedKind == null) {
                    storedKind = kind;
                }

                Logger.d(TAG, kind + "/" + storedKind);

                if (!kind.equals(storedKind)) {
                    finish();
                    return;
                }

                PreferenceUtil.setAnchor(getApplication(), kind);
            } catch (UnsupportedEncodingException e) {
                Logger.e(TAG, e);
            } catch (DecoderException e) {
                Logger.e(TAG, e);
            }

            if (twitter != null) {
                Logger.d(TAG, "Twitter is not null");

                Logger.d(TAG, "isLogin from server is " + isLogin);
                Logger.d(TAG, "isLogin from prefs is "
                        + PreferenceUtil.getPreference(getApplication()).getBoolean("isLogin", false));

                if (isLogin != PreferenceUtil.getPreference(getApplication()).getBoolean("isLogin", false)) {
                    PreferenceUtil.getPreference(getApplication()).edit().putLong(kind + isLogin, -1L).commit();
                }

                if (PreferenceUtil.isDifferentDate(getApplication(), kind + isLogin)) {
                    PreferenceUtil.getPreference(getApplication()).edit().putBoolean("isLogin", isLogin).commit();
                    TweetTask tTask = new TweetTask(twitter, isLogin);
                    tTask.setOnTweetResultListener(this);
                    long time = System.currentTimeMillis();
                    URLCodec codec = new URLCodec();

                    try {
                        msg = codec.decode(msg, "UTF-8");
                        PreferenceUtil.setClientMessage(getApplication(), msg, kind + isLogin);
                        msg = msg.replace("${client}", "").replace("${date}", CommonUtil.formatDate(time))
                                .toString();

                        Logger.d(TAG, msg);

                        StatusUpdate su = new StatusUpdate(msg);
                        tTask.exec(su);
                    } catch (UnsupportedEncodingException e) {
                        Logger.e(TAG, e);
                    } catch (DecoderException e) {
                        Logger.e(TAG, e);
                    }
                }
            }
        } else {
            Logger.d(TAG, "Twitter is null");
        }

        sendMessage(url);
    }

    @Override
    public void onPostedAll(boolean isLogin) {
    }

    @Override
    public void onPosted(Status status, boolean isLogin) {
        // This is called from another thread!
        sendMessage("tweet://" + status.getId() + ":" + status.getUser().getScreenName() + ":"
                + PreferenceUtil.getUUID(getApplication()) + ":" + isLogin);
    }
}