Java tutorial
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); } }