package net.screenfreeze.deskcon; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.media.RingtoneManager; import android.net.Uri; import android.os.Environment; import android.os.IBinder; import android.os.Looper; import android.os.SystemClock; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.telephony.SmsManager; import android.util.Log; import android.widget.Toast; public class ControlService extends Service { private static SharedPreferences sharedPrefs; private static int PORT; private static ControlServer controlserver; private static Toast SMSToastMessage; @Override public IBinder onBind(Intent intent) { return null; } @SuppressLint("ShowToast") @Override public void onCreate() { sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); SMSToastMessage = Toast.makeText(getApplicationContext(), "SMS Sent",Toast.LENGTH_LONG); PORT = Integer.parseInt(sharedPrefs.getString("control_port", "9096")); super.onCreate(); } @Override public void onDestroy() { Log.d("Control: ", "stop Server"); //controlserver.cancel(true); controlserver.stopServer(); super.onDestroy(); } // workaround: sys stops task when UI closes @SuppressLint("NewApi") @Override public void onTaskRemoved(Intent rootIntent){ Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass()); restartServiceIntent.setPackage(getPackageName()); PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarmService.set( AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent); super.onTaskRemoved(rootIntent); } @SuppressLint("NewApi") @Override public int onStartCommand(Intent intent, int flags, int startId) { controlserver = new ControlServer(); Thread cs = new Thread(controlserver); cs.start(); return START_STICKY; } private class ControlServer implements Runnable { private SSLServerSocket sslServerSocket; private SSLSocket socket; private boolean isStopped = false; @Override public void run() { Log.d("Control: ", "start Server"); try { // create SSLServerSocket sslServerSocket = Connection.createSSLServerSocket(getApplicationContext(), PORT); } catch (Exception e) { e.printStackTrace(); Log.d("Control: ", "could not start"); return; } //begin serving while (!isStopped) { try { socket = (SSLSocket) sslServerSocket.accept(); socket.startHandshake(); } catch (IOException e) { e.printStackTrace(); } if (socket != null && socket.isConnected()) { try { handleClientSocket(socket); socket.close(); } catch (Exception e) { e.printStackTrace(); } } } } private void handleClientSocket(SSLSocket socket) throws Exception { BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream()); // receive Data byte[] data = readWithMaxBuffer(inFromClient); String datastring = new String(data); outToClient.write("OK".getBytes()); Log.d("Control: ", "received CMD"); // parse CMD Data JSONObject jobject = new JSONObject(datastring); //Long uuid = jobject.getLong("uuid"); String name = jobject.getString("name"); String cmdtype = jobject.getString("type"); String cmddata = jobject.getString("data"); // SMS if (cmdtype.equals("sms")) { sendSMS(cmddata); } // PING else if (cmdtype.equals("ping")) { playPing(name); } // FILEUP else if (cmdtype.equals("fileup")) { Log.d("Control: ", "File Transfer"); JSONArray jarray = new JSONArray(cmddata); String[] filenames = new String[jarray.length()]; for (int i=0; i<jarray.length(); i++) { filenames[i] = jarray.getString(i); } receiveFiles(filenames, socket); publishProgress(1); } } private void publishProgress(int i) { Looper.prepare(); Toast finishedToast = Toast.makeText(getBaseContext(), "received File(s)", Toast.LENGTH_LONG); finishedToast.show(); } // force server stop private void stopServer() { isStopped = true; try { sslServerSocket.close(); } catch (IOException e) {} } } //stores sent sms in sent folder public boolean storeSMS(String number, String message) { boolean ret = false; try { ContentValues values = new ContentValues(); values.put("address", number); values.put("body", message); values.put("read", true); getContentResolver().insert(Uri.parse("content://sms/sent"), values); ret = true; } catch (Exception ex) { ret = false; } return ret; } public void sendSMS(String data) throws JSONException { JSONObject smsjobject = new JSONObject(data); String number = smsjobject.getString("number"); String message = smsjobject.getString("message"); SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(number, null, message, null, null); storeSMS(number,message); SMSToastMessage.show(); } // play default ringtone with Notification public void playPing(String data) { Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.connector_launcher) .setContentTitle("Ping!") .setContentText("from "+data) .setSound(ringtone); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(555, mBuilder.build()); } private void receiveFiles(String[] filenames, SSLSocket socket) throws IOException { DataInputStream dataInFromClient = new DataInputStream(socket.getInputStream()); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream()); File downloadfolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); for (int i=0; i<filenames.length; i++) { String filename = filenames[i]; // receive Filesize String ins = inFromClient.readLine(); long filesize = Long.parseLong(ins); byte[] buffer = new byte[4096]; int loopcnt = Math.round(filesize/4096); int lastbytes = (int) (filesize % 4096); // open File File newFile = new File(downloadfolder, filename); FileOutputStream fos = new FileOutputStream(newFile); // send ready outToClient.write(1); // send Data for (int j=0; j<loopcnt; j++) { dataInFromClient.read(buffer, 0, 4096); fos.write(buffer, 0, 4096); } dataInFromClient.read(buffer, 0, lastbytes); fos.write(buffer, 0, lastbytes); fos.flush(); fos.close(); } } public byte[] convertChartoByteArray(char[] chars) { byte[] bytes = String.valueOf(chars).getBytes(); return bytes; } private byte[] readWithMaxBuffer(BufferedReader inFromServer) throws IOException { char[] recvbuffer = new char[4096]; // avoid buffer overflow int readcnt = inFromServer.read(recvbuffer); char[] tmp_dataArray = new char[readcnt]; for (int i=0; i<tmp_dataArray.length; i++) { tmp_dataArray[i] = recvbuffer[i]; } byte[] data = convertChartoByteArray(tmp_dataArray); return data; } }