commit 291374b6e88f9c478234d217f1e8731590c8a95d Author: Victor Date: Thu Jul 11 13:28:06 2013 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6aab630 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.iml +*.iws +*.ipr +.idea/ +.gradle/ +local.properties + +*/build/ + +*~ +*.swp \ No newline at end of file diff --git a/SocketFileTransfer/build.gradle b/SocketFileTransfer/build.gradle new file mode 100644 index 0000000..5e08962 --- /dev/null +++ b/SocketFileTransfer/build.gradle @@ -0,0 +1,23 @@ +buildscript { + repositories { + maven { url 'http://repo1.maven.org/maven2' } + } + dependencies { + classpath 'com.android.tools.build:gradle:0.4' + } +} +apply plugin: 'android' + +dependencies { + compile files('libs/android-support-v4.jar') +} + +android { + compileSdkVersion 17 + buildToolsVersion "17.0.0" + + defaultConfig { + minSdkVersion 7 + targetSdkVersion 17 + } +} diff --git a/SocketFileTransfer/libs/android-support-v4.jar b/SocketFileTransfer/libs/android-support-v4.jar new file mode 100644 index 0000000..428bdbc Binary files /dev/null and b/SocketFileTransfer/libs/android-support-v4.jar differ diff --git a/SocketFileTransfer/src/main/AndroidManifest.xml b/SocketFileTransfer/src/main/AndroidManifest.xml new file mode 100644 index 0000000..930d4de --- /dev/null +++ b/SocketFileTransfer/src/main/AndroidManifest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SocketFileTransfer/src/main/ic_launcher-web.png b/SocketFileTransfer/src/main/ic_launcher-web.png new file mode 100644 index 0000000..6befbb5 Binary files /dev/null and b/SocketFileTransfer/src/main/ic_launcher-web.png differ diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/CursorActivity.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/CursorActivity.java new file mode 100644 index 0000000..1542a0e --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/CursorActivity.java @@ -0,0 +1,31 @@ +package com.annimon.socketfiletransfer; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Window; +import android.view.WindowManager; + +/** + * + * @author aNNiMON + */ +public class CursorActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Set fullscreen mode. + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + // Set backlight always on. + getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + TouchpadView view = new TouchpadView(this); + view.requestFocus(); + setContentView(view); + + new SocketTransferTask(OperationListener.MODE_CURSOR_CONTROL).execute(view); + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MainActivity.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MainActivity.java new file mode 100644 index 0000000..feaab22 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MainActivity.java @@ -0,0 +1,138 @@ +package com.annimon.socketfiletransfer; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.app.Activity; +import android.provider.MediaStore; +import android.view.Menu; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.Toast; + +import java.io.File; + +public class MainActivity extends Activity implements View.OnClickListener { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // We don't need to show UI if sharing data. + if (checkSharingData()) { + finish(); + } + + LayoutParams layoutParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + layout.setLayoutParams(layoutParam); + + // Create main menu + String[] items = getResources().getStringArray(R.array.main_menu); + for (int i = 0; i < items.length; i++) { + String item = items[i]; + + Button button = new Button(this); + button.setLayoutParams(layoutParam); + button.setTag(i); + button.setText(item); + button.setOnClickListener(this); + + layout.addView(button); + } + + setContentView(layout); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + @Override + public void onClick(View view) { + final int id = (Integer) view.getTag(); + switch (id) { + case OperationListener.MODE_SERVER: + break; + + case OperationListener.MODE_FILE_TRANSFER: + onFileTransfer(); + break; + + case OperationListener.MODE_MESSAGE_TRANSFER: + Intent msgIntent = new Intent(this, MessagesActivity.class); + startActivity(msgIntent); + break; + + case OperationListener.MODE_CURSOR_CONTROL: + Intent curIntent = new Intent(this, CursorActivity.class); + startActivity(curIntent); + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != Activity.RESULT_OK) return; + + if (requestCode == OperationListener.MODE_FILE_TRANSFER) { + sendFile(data.getData()); + } + } + + private void sendFile(Uri uri) { + if (uri == null) return; + + String path = uri.getPath(); + if (uri.getScheme().startsWith("content")) path = getRealPathFromURI(uri); + + File file = new File(path); + new SocketTransferTask(OperationListener.MODE_FILE_TRANSFER).execute(file); + } + + private String getRealPathFromURI(Uri contentUri) { + String[] projection = { MediaStore.Images.Media.DATA }; + Cursor cursor = managedQuery(contentUri, projection, null, null, null); + int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + return cursor.getString(columnIndex); + } + + private void onFileTransfer() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("file/*"); + try { + startActivityForResult(intent, OperationListener.MODE_FILE_TRANSFER); + } catch (ActivityNotFoundException e) { + Toast.makeText(this, getString(R.string.app_not_found), Toast.LENGTH_SHORT).show(); + } + } + + private boolean checkSharingData() { + Intent intent = getIntent(); + String type = intent.getType(); + if (Intent.ACTION_SEND.equals(intent.getAction()) && type != null) { + if (type.startsWith("file/") || type.startsWith("image/")) { + Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); + sendFile(uri); + return true; + } else if ("text/plain".equals(type)) { + String text = intent.getStringExtra(Intent.EXTRA_TEXT); + new SocketTransferTask(OperationListener.MODE_MESSAGE_TRANSFER).execute(text); + return true; + } + } + return false; + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MessagesActivity.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MessagesActivity.java new file mode 100644 index 0000000..44a9005 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/MessagesActivity.java @@ -0,0 +1,37 @@ +package com.annimon.socketfiletransfer; + +import android.os.Bundle; +import android.app.Activity; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.annimon.socketfiletransfer.util.MessageHistory; + +public class MessagesActivity extends Activity implements View.OnClickListener { + + private EditText editText; + private TextView messagesHistory; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_messages); + + findViewById(R.id.send_text_button).setOnClickListener(this); + editText = (EditText) findViewById(R.id.message_edit_text); + messagesHistory = (TextView) findViewById(R.id.messages_history); + + messagesHistory.setText(MessageHistory.getAllText()); + } + + @Override + public void onClick(View view) { + String text = editText.getText().toString(); + new SocketTransferTask(OperationListener.MODE_MESSAGE_TRANSFER).execute(text); + editText.setText(""); + + MessageHistory.addMessage(" >> " + text); + messagesHistory.setText(MessageHistory.getAllText()); + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationListener.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationListener.java new file mode 100644 index 0000000..ee1a30d --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationListener.java @@ -0,0 +1,73 @@ +package com.annimon.socketfiletransfer; + +import com.annimon.socketfiletransfer.operations.MessageOperation; +import com.annimon.socketfiletransfer.operations.FileOperation; +import com.annimon.socketfiletransfer.operations.Operation; +import com.annimon.socketfiletransfer.util.ExceptionHandler; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +/** + * Прослушивание операций с данными. + * @author aNNiMON + */ +public class OperationListener { + + public static final int + MODE_SERVER = 0, + MODE_FILE_TRANSFER = 1, + MODE_MESSAGE_TRANSFER = 2, + MODE_CURSOR_CONTROL = 3; + + protected DataInputStream dis; + protected DataOutputStream dos; + + public void setSocket(Socket socket) { + try { + dis = new DataInputStream( socket.getInputStream() ); + dos = new DataOutputStream( socket.getOutputStream() ); + } catch (IOException ex) { + ExceptionHandler.log(ex); + } + } + + public void listenOperation() throws Exception { + int mode = dis.readInt(); + Operation operation; + switch(mode) { + case MODE_FILE_TRANSFER: + operation = new FileOperation(dis); + break; + case MODE_MESSAGE_TRANSFER: + operation = new MessageOperation(dis); + break; +// case MODE_CURSOR_CONTROL: +// operation = new CursorOperation(dis); +// break; + default: + return; + } + if (operation != null) { + operation.startServerSide(); + } + } + + public void close() { + if (dis != null) { + try { + dis.close(); + } catch (IOException ex) { + ExceptionHandler.log(ex); + } + } + if (dos != null) { + try { + dos.close(); + } catch (IOException ex) { + ExceptionHandler.log(ex); + } + } + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationManager.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationManager.java new file mode 100644 index 0000000..60c3f17 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/OperationManager.java @@ -0,0 +1,32 @@ +package com.annimon.socketfiletransfer; + +import com.annimon.socketfiletransfer.operations.CursorOperation; +import com.annimon.socketfiletransfer.operations.FileOperation; +import com.annimon.socketfiletransfer.operations.MessageOperation; +import com.annimon.socketfiletransfer.operations.Operation; + +/** + * Manage data operations. + * @author aNNiMON + */ +public class OperationManager extends OperationListener { + + public void execute(int mode, Object... params) throws Exception { + Operation operation = null; + switch (mode) { + case MODE_FILE_TRANSFER: + operation = new FileOperation(dos); + break; + case MODE_MESSAGE_TRANSFER: + operation = new MessageOperation(dos); + break; + case MODE_CURSOR_CONTROL: + operation = new CursorOperation(dos); + break; + } + if (operation != null) { + operation.startClientSide(params); + } + } + +} \ No newline at end of file diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/SocketTransferTask.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/SocketTransferTask.java new file mode 100644 index 0000000..a43764f --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/SocketTransferTask.java @@ -0,0 +1,40 @@ +package com.annimon.socketfiletransfer; + +import android.os.AsyncTask; +import android.util.Log; + +import java.net.Socket; + +public class SocketTransferTask extends AsyncTask { + + /** Transfer mode */ + private int mode; + + public SocketTransferTask(int mode) { + this.mode = mode; + } + + @Override + protected Boolean doInBackground(Object... objects) { + boolean success = true; + OperationManager manager = new OperationManager(); + try { + Socket socket = new Socket("192.168.1.35", 7119); + manager.setSocket(socket); + manager.execute(mode, objects); + } catch (Exception e) { + success = false; + e.printStackTrace(); + Log.e("SFT", e.getMessage(), e); + } finally { + if (manager != null) manager.close(); + } + + return success; + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/TouchpadView.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/TouchpadView.java new file mode 100644 index 0000000..361c00c --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/TouchpadView.java @@ -0,0 +1,43 @@ +package com.annimon.socketfiletransfer; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.util.AttributeSet; +import android.view.View; + +/** + * @author aNNiMON + */ +public class TouchpadView extends View { + + public TouchpadView(Context context) { + super(context); + initView(); + } + + public TouchpadView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public TouchpadView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + setFocusable(true); + setFocusableInTouchMode(true); + } + + public void closeActivity() { + ((Activity)getContext()).finish(); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawColor(Color.GRAY); + } +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/CursorOperation.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/CursorOperation.java new file mode 100644 index 0000000..cc95c65 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/CursorOperation.java @@ -0,0 +1,149 @@ +package com.annimon.socketfiletransfer.operations; + +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; + +import com.annimon.socketfiletransfer.OperationListener; +import com.annimon.socketfiletransfer.TouchpadView; +import com.annimon.socketfiletransfer.util.ExceptionHandler; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * @author aNNiMON + */ +public class CursorOperation implements Operation { + + private static final int + NONE = -1, + TYPE_MOVE = 1, + TYPE_CLICK = 2, + TYPE_DRAG = 3, + TYPE_RELEASED = 4, + TYPE_KEY_RELEASED = 5, + STOP = 10; + + private DataInputStream dis; + private DataOutputStream dos; + + private boolean running; + + public CursorOperation(DataInputStream dis) { + this.dis = dis; + } + + public CursorOperation(DataOutputStream dos) { + this.dos = dos; + } + + @Override + public void startServerSide() throws Exception { + + } + + @Override + public void startClientSide(Object... params) throws Exception { + TouchpadView view = (TouchpadView) params[0]; + running = true; + + dos.writeInt(OperationListener.MODE_CURSOR_CONTROL); + + // Send view size + dos.writeInt(view.getWidth()); + dos.writeInt(view.getHeight()); + + view.requestFocus(); + view.setOnTouchListener(touchListener); + view.setOnKeyListener(keyListener); + + while(running) { + Thread.sleep(10); + } + + view.closeActivity(); + } + + private View.OnTouchListener touchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (!running) return true; + + int x = (int) motionEvent.getX(); + int y = (int) motionEvent.getY(); + int action = motionEvent.getAction() & MotionEvent.ACTION_MASK; + + if (action == MotionEvent.ACTION_DOWN) { + try { + dos.writeInt(TYPE_MOVE); + dos.writeInt(x); + dos.writeInt(y); + } catch (IOException ex) { } + // Click event + if (motionEvent.getPointerCount() > 1) { + try { + dos.writeInt(TYPE_CLICK); + int mask = motionEvent.getPointerCount() - 2; + dos.writeInt(16 >> mask); + } catch (IOException ex) { } + } + } else if ( (action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL) ) { + try { + dos.writeInt(TYPE_RELEASED); + } catch (IOException ex) { } + } else if (action == MotionEvent.ACTION_MOVE) { + try { + dos.writeInt(TYPE_DRAG); + dos.writeInt(x); + dos.writeInt(y); + } catch (IOException ex) { } + } + + return true; + } + }; + + private View.OnKeyListener keyListener = new View.OnKeyListener() { + + @Override + public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { + if (!running) return true; + + if (keyEvent.getAction() == KeyEvent.ACTION_UP) { + try { + dos.writeInt(TYPE_KEY_RELEASED); + dos.writeInt(convertToAscii(keyCode)); + } catch (IOException e) { + ExceptionHandler.log(e); + } + + if (keyCode == KeyEvent.KEYCODE_BACK) { + running = false; + } + } + return true; + } + + private int convertToAscii(int key) { + if (key >= KeyEvent.KEYCODE_A && key <= KeyEvent.KEYCODE_Z) + return key - KeyEvent.KEYCODE_A + 'A'; + else if (key >= KeyEvent.KEYCODE_0 && key <= KeyEvent.KEYCODE_9) + return key - KeyEvent.KEYCODE_0 + '0'; + else if (key == KeyEvent.KEYCODE_ENTER) return 10; + else if (key == KeyEvent.KEYCODE_SHIFT_LEFT || + key == KeyEvent.KEYCODE_SHIFT_RIGHT) return 0x16; + else if (key == KeyEvent.KEYCODE_SPACE) return 32; + else if (key == KeyEvent.KEYCODE_DEL) return 8; // Backspace + else if (key == KeyEvent.KEYCODE_MENU) return 525; // Context Menu + else if (key == KeyEvent.KEYCODE_VOLUME_UP) return 33; // Page up + else if (key == KeyEvent.KEYCODE_VOLUME_DOWN) return 34; // Page down + else if (key == KeyEvent.KEYCODE_DPAD_LEFT) return 37; + else if (key == KeyEvent.KEYCODE_DPAD_UP) return 38; + else if (key == KeyEvent.KEYCODE_DPAD_RIGHT) return 39; + else if (key == KeyEvent.KEYCODE_DPAD_DOWN) return 40; + else return key; + } + }; +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/FileOperation.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/FileOperation.java new file mode 100644 index 0000000..96300c5 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/FileOperation.java @@ -0,0 +1,78 @@ +package com.annimon.socketfiletransfer.operations; + +import com.annimon.socketfiletransfer.MainActivity; +import com.annimon.socketfiletransfer.OperationListener; +import com.annimon.socketfiletransfer.OperationManager; +import com.annimon.socketfiletransfer.util.ExceptionHandler; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * + * @author aNNiMON + */ +public class FileOperation implements Operation { + + private static final int BUFFER_SIZE = 1024; + + private DataInputStream dis; + private DataOutputStream dos; + + public FileOperation(DataInputStream dis) { + this.dis = dis; + } + + public FileOperation(DataOutputStream dos) { + this.dos = dos; + } + + @Override + public void startServerSide() { + FileOutputStream fout = null; + try { + String name = dis.readUTF(); + fout = new FileOutputStream("/mnt/sdcard/" + name);//Config.getTransferDir() + name); + byte[] buffer = new byte[BUFFER_SIZE]; + int count; + while ((count = dis.read(buffer, 0, BUFFER_SIZE)) != -1) { + fout.write(buffer, 0, count); + } + fout.flush(); + fout.close(); + } catch (IOException ex) { + ExceptionHandler.log(ex); + } finally { + try { + fout.close(); + } catch (IOException ex) { + ExceptionHandler.log(ex); + } + } + } + + @Override + public void startClientSide(Object... params) throws Exception { + File file = (File) params[0]; + + dos.writeInt(OperationListener.MODE_FILE_TRANSFER); + + String name = file.getName(); + dos.writeUTF(name); + + FileInputStream fis = new FileInputStream(file); + byte[] buffer = new byte[BUFFER_SIZE]; + int count; + while ((count = fis.read(buffer, 0, BUFFER_SIZE)) != -1) { + dos.write(buffer, 0, count); + } + dos.flush(); + fis.close(); + } + +} + diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/MessageOperation.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/MessageOperation.java new file mode 100644 index 0000000..da550a3 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/MessageOperation.java @@ -0,0 +1,42 @@ +package com.annimon.socketfiletransfer.operations; + +import android.util.Log; + +import com.annimon.socketfiletransfer.OperationListener; +import com.annimon.socketfiletransfer.util.MessageHistory; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * + * @author aNNiMON + */ +public class MessageOperation implements Operation { + + private DataInputStream dis; + private DataOutputStream dos; + + public MessageOperation(DataInputStream dis) { + this.dis = dis; + } + + public MessageOperation(DataOutputStream dos) { + this.dos = dos; + } + + @Override + public void startServerSide() throws IOException { + String text = dis.readUTF(); + MessageHistory.addMessage(text); + } + + @Override + public void startClientSide(Object... params) throws Exception { + String message = (String) params[0]; + + dos.writeInt(OperationListener.MODE_MESSAGE_TRANSFER); + dos.writeUTF(message); + } + +} diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/Operation.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/Operation.java new file mode 100644 index 0000000..2360e8d --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/operations/Operation.java @@ -0,0 +1,13 @@ +package com.annimon.socketfiletransfer.operations; + +/** + * + * @author aNNiMON + */ +public interface Operation { + + void startServerSide() throws Exception; + + void startClientSide(Object... params) throws Exception; + +} \ No newline at end of file diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/ExceptionHandler.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/ExceptionHandler.java new file mode 100644 index 0000000..43689fb --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/ExceptionHandler.java @@ -0,0 +1,61 @@ +package com.annimon.socketfiletransfer.util; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.util.Log; + +/** + * Handling exceptions. + * If error is critical or must be show to user, then + * call alert method. + * In other situations call log method. + * + * @author aNNiMON + */ +public class ExceptionHandler { + + private static final boolean DEBUG = false; + private static final String TAG = "ExceptionHandler"; + + public static void alert(Context context, Exception ex) { + alert(context, getErrorMessage(ex)); + } + + public static void alert(Context context, int resourceId) { + alert(context, context.getString(resourceId)); + } + + public static void alert(Context context, String message) { + new AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(android.R.string.dialog_alert_title) + .setMessage(message) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + + }).show(); + } + + public static void log(Exception ex) { + if (DEBUG) { + Log.e(TAG, getErrorMessage(ex)); + } + } + + public static void log(String message) { + if (DEBUG) { + Log.e(TAG, message); + } + } + + private static String getErrorMessage(Exception ex) { + return ex.getMessage(); + } + +} \ No newline at end of file diff --git a/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/MessageHistory.java b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/MessageHistory.java new file mode 100644 index 0000000..1cff0d2 --- /dev/null +++ b/SocketFileTransfer/src/main/java/com/annimon/socketfiletransfer/util/MessageHistory.java @@ -0,0 +1,25 @@ +package com.annimon.socketfiletransfer.util; + +/** + * + * @author aNNiMON + */ +public class MessageHistory { + + private static String lastMessage = ""; + private static StringBuilder allText = new StringBuilder(); + + public static void addMessage(String message) { + lastMessage = message; + allText.append(message).append("\r\n\r\n"); + } + + public static String getLastMessage() { + return lastMessage; + } + + public static String getAllText() { + return allText.toString(); + } + +} diff --git a/SocketFileTransfer/src/main/res/drawable-hdpi/ic_launcher.png b/SocketFileTransfer/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..3a8de7f Binary files /dev/null and b/SocketFileTransfer/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/SocketFileTransfer/src/main/res/drawable-mdpi/ic_launcher.png b/SocketFileTransfer/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..24d152d Binary files /dev/null and b/SocketFileTransfer/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/SocketFileTransfer/src/main/res/drawable-xhdpi/ic_launcher.png b/SocketFileTransfer/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..5c748a8 Binary files /dev/null and b/SocketFileTransfer/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/SocketFileTransfer/src/main/res/drawable-xxhdpi/ic_launcher.png b/SocketFileTransfer/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..5fdb88c Binary files /dev/null and b/SocketFileTransfer/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/SocketFileTransfer/src/main/res/layout/activity_messages.xml b/SocketFileTransfer/src/main/res/layout/activity_messages.xml new file mode 100644 index 0000000..327de72 --- /dev/null +++ b/SocketFileTransfer/src/main/res/layout/activity_messages.xml @@ -0,0 +1,29 @@ + + + + +