package net.screenfreeze.deskcon;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Formatter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class DesktopHostsActivity extends Activity {
private DesktopHostsDBHelper dbhelper;
private AuthenticationManager authenticationmanager;
private ListView hostslistview;
private static DiscoveryTask responseserver;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.desktop_hosts);
dbhelper = new DesktopHostsDBHelper(this);
authenticationmanager = new AuthenticationManager(this);
ImageView addButton = (ImageView) findViewById(R.id.hostsaddimageView);
hostslistview = (ListView) findViewById(R.id.hostslistView);
addButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showAddHostDialog();
}
});
loadHostlist();
//testreaddb();
}
@Override
protected void onDestroy() {
dbhelper.close();
super.onDestroy();
}
private void loadHostlist() {
hostslistview.removeAllViewsInLayout();
HostsAdapter ha = new HostsAdapter(this, dbhelper.getAllCursor());
hostslistview.setAdapter(ha);
hostslistview.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View parent,
int pos, long id) {
Cursor cursor = dbhelper.getHostByIdCursor(id);
String ip = cursor.getString(2);
int port = cursor.getInt(3);
String wifi = cursor.getString(6);
cursor.close();
showEditHostDialog(id, ip, port, wifi);
return false;
}
});
hostslistview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View parent, int pos,
long id) {
Cursor cursor = dbhelper.getHostByIdCursor(id);
String host = cursor.getString(2);
int port = cursor.getInt(3);
cursor.close();
Intent i = new Intent(getApplicationContext(), StatusUpdateService.class);
i.putExtra("commandtype", "PING");
i.putExtra("message", "");
i.putExtra("host", host);
i.putExtra("port", port);
startService(i);
Toast pingmsg = Toast.makeText(getApplicationContext(),
"send Ping", Toast.LENGTH_SHORT);
pingmsg.show();
}
});
}
@SuppressWarnings("unused")
private void testreaddb() {
Cursor cursor = dbhelper.getHostsOnWifiCursor("<unknown ssid>");
System.out.println(cursor.getCount());
if (cursor.moveToFirst()) {
do {
System.out.println(cursor.getLong(0));
System.out.println(cursor.getString(2));
System.out.println(cursor.getInt(3));
//System.out.println(cursor.getString(6));
} while (cursor.moveToNext());
}
}
private void showAddHostDialog() {
LayoutInflater li = getLayoutInflater();
View addhostView = li.inflate(R.layout.add_host_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setView(addhostView);
alertDialogBuilder.setTitle("Pair with Desktop");
alertDialogBuilder.setCancelable(true);
final EditText ipedittext = (EditText) addhostView.findViewById(R.id.newipeditText);
final EditText portedittext = (EditText) addhostView.findViewById(R.id.newporteditText);
final CheckBox wifilockcheckbox = (CheckBox) addhostView.findViewById(R.id.wifilockcheckBox);
ListView foundHostsListView = (ListView) addhostView.findViewById(R.id.foundlistView);
ArrayList<DesktopHost> as = new ArrayList<DesktopHost>();
//as.add(new DesktopHost("Hans", "192.168.55.66", 34553, 51674));
final DiscoveredHostsAdapter dha = new DiscoveredHostsAdapter(getApplicationContext(), as);
responseserver = new DiscoveryTask(dha);
final String wifi = getWifiSSID();
wifilockcheckbox.setText("only on "+wifi);
foundHostsListView.setAdapter(dha);
foundHostsListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
DesktopHost desk = dha.getItem(position);
if (wifilockcheckbox.isChecked()) {
authenticationmanager.pairWithHost(desk.ip, desk.port, wifi, new OnPairCallback());
}
else {
authenticationmanager.pairWithHost(desk.ip, desk.port, "", new OnPairCallback());
}
responseserver.stopServer();
}
});
alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String ip = ipedittext.getText().toString();
int port = Integer.parseInt(portedittext.getText().toString());
if (wifilockcheckbox.isChecked()) {
authenticationmanager.pairWithHost(ip, port, wifi, new OnPairCallback());
}
else {
authenticationmanager.pairWithHost(ip, port, "", new OnPairCallback());
}
responseserver.cancel(true);
dialog.cancel();
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
responseserver.stopServer();
dialog.cancel();
}
});
responseserver.execute();
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
// Edit a Host
private void showEditHostDialog(final long id, String ip, int port, String wifi) {
LayoutInflater li = getLayoutInflater();
View addhostView = li.inflate(R.layout.add_host_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setView(addhostView);
alertDialogBuilder.setTitle("Edit Desktop");
alertDialogBuilder.setCancelable(true);
final EditText ipedittext = (EditText) addhostView.findViewById(R.id.newipeditText);
final EditText portedittext = (EditText) addhostView.findViewById(R.id.newporteditText);
final CheckBox wifilockcheckbox = (CheckBox) addhostView.findViewById(R.id.wifilockcheckBox);
final String currentwifi;
ipedittext.setText(ip);
portedittext.setText(""+port);
if (wifi.equals("")) {
wifilockcheckbox.setChecked(false);
currentwifi = getWifiSSID();
wifilockcheckbox.setText("only on "+currentwifi);
}
else {
wifilockcheckbox.setChecked(true);
currentwifi = wifi;
wifilockcheckbox.setText("only on "+currentwifi);
}
alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String ip = ipedittext.getText().toString();
int port = Integer.parseInt(portedittext.getText().toString());
if (wifilockcheckbox.isChecked()) {
// update DB
dbhelper.updateHost(id, ip, port, currentwifi);
}
else {
// update DB
dbhelper.updateHost(id, ip, port, "");
}
loadHostlist();
dialog.cancel();
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
// get current SSID of connected Wifi
private String getWifiSSID() {
String ssid = "";
WifiManager wifiManager = (WifiManager) getApplicationContext()
.getSystemService(Context.WIFI_SERVICE);
try {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
ssid = wifiInfo.getSSID();
} catch (Exception a) { }
if (ssid == null) {ssid = "";}
return ssid;
}
public class DiscoveredHostsAdapter extends ArrayAdapter<DesktopHost> {
public DiscoveredHostsAdapter(Context context,
ArrayList<DesktopHost> objects) {
super(context,R.layout.host_list_row_share,objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
DesktopHost desktop = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.host_list_row_share, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.hostnametextView);
TextView tvip = (TextView) convertView.findViewById(R.id.hostiptextView);
TextView tvid = (TextView) convertView.findViewById(R.id.hostidtextView);
TextView tvwifi = (TextView) convertView.findViewById(R.id.wifitextView);
// Populate the data into the template view using the data object
tvName.setText(desktop.name);
tvip.setText(desktop.ip);
tvid.setText(""+desktop.uuid);
tvwifi.setText("");
return convertView;
}
}
private class DiscoveryTask extends AsyncTask<Void, Void, Void> {
private DatagramSocket serverSocketUDP;
private boolean isStopped = false;
private DiscoveredHostsAdapter dha;
public DiscoveryTask(DiscoveredHostsAdapter dha) {
this.dha = dha;
}
@Override
protected Void doInBackground(Void... params) {
Log.d("Discovery: ", "start UDP Server");
String data = "0::deskcon";
try {
// Send "Ask for Hosts" Broadcast
serverSocketUDP = new DatagramSocket(5108);
serverSocketUDP.setBroadcast(true);
InetAddress local = getBroadcast();
// has a broadcast address been found
if (local == null) {
Log.d("Discovery: ", "no Broadcast Address found");
return null;
}
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), local, 5108);
serverSocketUDP.send(packet);
} catch (Exception e) {
e.printStackTrace();
Log.d("Discovery: ", "could not start");
return null;
}
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("net.screenfreeze.deskcon");
lock.acquire();
// Receive responses from desktop hosts
while (!isStopped) {
byte[] receiveData = new byte[128];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
serverSocketUDP.receive(receivePacket);
} catch (Exception e) {}
final InetAddress address = receivePacket.getAddress();
String msg = new String(receiveData, 0, receivePacket.getLength());
// Check for valid msg
boolean isvalismsg = msg.split("::").length == 3;
// Process msg if it is not our own broadcast msg
if (!msg.equals(data) && !isStopped && isvalismsg) {
final DesktopHost desktop = handleReceiveUdp(msg, address);
Log.d("udp from: ", "msg "+msg+" "+address);
runOnUiThread(new Runnable() {
@Override
public void run() {
dha.add(desktop);
}
});
}
}
lock.release();
return null;
}
private DesktopHost handleReceiveUdp(String msg, InetAddress address) {
String[] split = msg.split("::");
long uuid = Long.parseLong(split[0]);
String hostname = split[1];
int port = Integer.parseInt(split[2]);
return new DesktopHost(hostname, ""+address.getHostAddress(), port, uuid);
}
// force server stop
private void stopServer() {
isStopped = true;
try {
serverSocketUDP.close();
}
catch (Exception e) {}
}
}
public class HostsAdapter extends CursorAdapter {
@SuppressWarnings("deprecation")
public HostsAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
public void bindView(View view, final Context context, Cursor cursor) {
TextView idtv = (TextView) view.findViewById(R.id.hostidtextView);
TextView nametv = (TextView) view.findViewById(R.id.hostnametextView);
TextView iptv = (TextView) view.findViewById(R.id.hostiptextView);
TextView wifitv = (TextView) view.findViewById(R.id.wifitextView);
ImageView deleteiv = (ImageView) view.findViewById(R.id.deletehostimageView);
final long id = cursor.getLong(0);
nametv.setText(cursor.getString(1));
idtv.setText(String.valueOf(cursor.getLong(4)));
iptv.setText(cursor.getString(2));
wifitv.setText(cursor.getString(6));
deleteiv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showRemoveHostDialog(context, id);
}
});
}
// remove Host Dialog
private void showRemoveHostDialog(Context context, final long id) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle("Remove Desktop");
alertDialogBuilder.setMessage("You want to remove\n"+id+" ?");
alertDialogBuilder.setCancelable(true);
alertDialogBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dbhelper.removeHost(id);
authenticationmanager.deleteCertificate(id);
loadHostlist();
}
});
alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.host_list_row, parent, false);
return v;
}
}
public interface OnPairListener{
void onPairingCompleted();
}
public class OnPairCallback implements OnPairListener{
@Override
public void onPairingCompleted() {
loadHostlist();
}
}
public class DesktopHost {
public String name;
public String ip;
public int port;
public long uuid;
public DesktopHost(String name, String ip, int port, long uuid) {
this.name = name;
this.ip = ip;
this.port = port;
this.uuid = uuid;
}
}
public static InetAddress getBroadcast(){
InetAddress found_bcast_address=null;
System.setProperty("java.net.preferIPv4Stack", "true");
try
{
Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
while (niEnum.hasMoreElements())
{
NetworkInterface ni = niEnum.nextElement();
if(!ni.isLoopback()){
for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses())
{
found_bcast_address = interfaceAddress.getBroadcast();
}
}
}
}
catch (SocketException e)
{
e.printStackTrace();
}
return found_bcast_address;
}
public InetAddress getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress;
}
}
}
} catch (SocketException ex) {}
return null;
}
}