import java.net.*; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class UdpProxy { public static void main(String[] args) throws Exception { boolean testMode = args.length == 0; String serverHost; int serverPort; int proxyPort; if (args.length != 3 && !testMode) { System.out.println("Use: java UdpProxy <serverhost> <serverport> <proxyport>"); return; } if (!testMode) { serverHost = args[0]; serverPort = Integer.parseInt(args[1]); proxyPort = Integer.parseInt(args[2]); } else { serverHost = "192.168.1.114"; serverPort = 19132; proxyPort = 19133; } new UdpProxy(serverHost, serverPort, proxyPort).runServer(); } static final int CONNECTION_TIMEOUT = 60000; HashMap<InetSocketAddress, ChannelInfo> channelMap = new HashMap<InetSocketAddress, ChannelInfo>(); InetSocketAddress serverAddress; int proxyPort; public UdpProxy(String serverHost, int serverPort, int proxyPort) throws Exception { InetAddress resolvedAddress = InetAddress.getByName(serverHost); this.serverAddress = new InetSocketAddress(resolvedAddress, serverPort); this.proxyPort = proxyPort; } public void runServer() throws Exception { System.out.println("Listening on " + proxyPort + ", forwarding to " + serverAddress); ByteBuffer buff = ByteBuffer.allocate(1024*1024); //this is probably more than necessary Selector selector = Selector.open(); DatagramChannel proxyChannel = addChannel(selector, proxyPort); long connectionTestTime = System.currentTimeMillis(); while (true) { try { selector.select(10000); //selector.selectNow(); Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); keyIterator.remove(); if (key.isReadable()) { DatagramChannel currentChannel = (DatagramChannel) key.channel(); InetSocketAddress localAddress = (InetSocketAddress) currentChannel.socket().getLocalSocketAddress(); buff.clear(); InetSocketAddress remoteAddress = (InetSocketAddress) currentChannel.receive(buff); buff.flip(); if (!fromServer(remoteAddress)) { ChannelInfo info = channelMap.get(remoteAddress); if (info == null) { DatagramChannel tempChannel = addChannel(selector, serverAddress); InetSocketAddress tempAddress = (InetSocketAddress) tempChannel.socket().getLocalSocketAddress(); info = new ChannelInfo(tempChannel, remoteAddress); channelMap.put(remoteAddress, info); System.out.println("Added key = " + remoteAddress.toString()); channelMap.put(tempAddress, info); System.out.println("Added key = " + tempAddress.toString()); } info.rxTime = System.currentTimeMillis(); info.channel.send(buff, serverAddress); } else { ChannelInfo info = channelMap.get(localAddress); if (info != null) { proxyChannel.send(buff, info.remoteAddress); } } } } //Test & remove old connections if (System.currentTimeMillis() - connectionTestTime >= CONNECTION_TIMEOUT) { connectionTestTime = System.currentTimeMillis(); Iterator<Map.Entry<InetSocketAddress, ChannelInfo>> entryIterator = channelMap.entrySet().iterator(); while (entryIterator.hasNext()) { Map.Entry<InetSocketAddress, ChannelInfo> entry = entryIterator.next(); InetSocketAddress address = entry.getKey(); ChannelInfo info = entry.getValue(); if (connectionTestTime - info.rxTime >= CONNECTION_TIMEOUT) { info.channel.close(); entryIterator.remove(); System.out.println("Removed key = " + address.toString()); } } } } catch (Exception ex) { ex.printStackTrace(); } } } public boolean fromServer(InetSocketAddress address) { return address.getAddress().equals(serverAddress.getAddress()); } public DatagramChannel addChannel(Selector selector, int bindPort) throws Exception { DatagramChannel channel = DatagramChannel.open(); channel.configureBlocking(false); channel.socket().bind(new InetSocketAddress(bindPort)); channel.register(selector, SelectionKey.OP_READ); return channel; } public DatagramChannel addChannel(Selector selector, InetSocketAddress address) throws Exception { DatagramChannel channel = DatagramChannel.open(); channel.configureBlocking(false); channel.connect(address); channel.register(selector, SelectionKey.OP_READ); return channel; } public static class ChannelInfo { public ChannelInfo() { } public ChannelInfo(DatagramChannel channel, InetSocketAddress remoteAddress) { this.channel = channel; this.localAddress = (InetSocketAddress) channel.socket().getLocalSocketAddress(); this.remoteAddress = remoteAddress; } DatagramChannel channel; InetSocketAddress localAddress; InetSocketAddress remoteAddress; long rxTime; } }
Saturday, October 26, 2013
UDP Proxy / Minecraft PE Proxy
Saturday, March 23, 2013
Show / Hide Android Soft Keyboard
Here is a helpful utility class for showing and hiding the Android soft keyboard. The code is written in C# using Mono for Android but should be easy to convert to Java. Similar behavior can be accomplished using Window.SetSoftInputMode but unfortunately SetSoftInputMode doesn't always play well with a tab / fragment architecture.
This code is my attempt to simplify the process of manually showing and hiding of the soft keyboard, which is much more complicated than it has a right to be (I blame vague documentation). My earlier attempts to accomplish this were laden with frustrating bugs and strange side-effects. Now, (hopefully) all those bugs and side-effects have been corrected.
By default there is a 200 millisecond delay on the ShowSoftKeyboard method; this is to accommodate any fragment transition animations that may occur. Showing the keyboard while running an animation can result in poor performance so the workaround is to wait until the animation is finished. If you are not using fragment transition animations then the delay can be eliminated.
*Code has been tested on a handful of real devices as well as a wide range of emulator versions (2.2+).
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Views.InputMethods; using Android.InputMethodServices; using Android.Util; namespace Mobile.Util { public static class ActivityExtensions { public static void HideSoftKeyboard(this Activity activity) { new Handler().Post(delegate { var view = activity.CurrentFocus; if (view != null) { InputMethodManager manager = (InputMethodManager)activity.GetSystemService(Context.InputMethodService); manager.HideSoftInputFromWindow(view.WindowToken, 0); } }); } public static void ShowSoftKeyboard(this Activity activity, View view = null, int delay = 200) { new Handler().PostDelayed(delegate { view = view ?? activity.CurrentFocus; if (view != null) { if (view.HasFocus) view.ClearFocus(); //bug fix for older versions of android view.RequestFocus(); InputMethodManager manager = (InputMethodManager)activity.GetSystemService(Context.InputMethodService); manager.ShowSoftInput(view, 0); } }, delay); } } public static class DialogExtensions { public static void HideSoftKeyboard(this Dialog dialog) { new Handler().Post(delegate { var view = dialog.CurrentFocus; if (view != null) { InputMethodManager manager = (InputMethodManager)dialog.Context.GetSystemService(Context.InputMethodService); manager.HideSoftInputFromWindow(view.WindowToken, 0); } }); } public static void ShowSoftKeyboard(this Dialog dialog, View view = null, int delay = 200) { new Handler().PostDelayed(delegate { view = view ?? dialog.CurrentFocus; if (view != null) { if (view.HasFocus) view.ClearFocus(); //bug fix for older versions of android view.RequestFocus(); InputMethodManager manager = (InputMethodManager)dialog.Context.GetSystemService(Context.InputMethodService); manager.ShowSoftInput(view, 0); } }, delay); } } }
Friday, February 22, 2013
Raspberry Pi
Raspberry Pi Model B