shithub: drawterm-fdroid

ref: 0818148b0432a1b11d2feb72cca47156a603e884
dir: /gui-android/java/org/echoline/drawterm/MainActivity.java/

View raw version
package org.echoline.drawterm;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Environment;

import android.app.Activity;

import android.app.Notification;
import android.app.NotificationManager;

import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseIntArray;
import android.util.Size;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.view.Surface;
import android.view.inputmethod.InputMethodManager;
import android.view.KeyEvent;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.CheckBox;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.graphics.ImageFormat;
import android.os.Handler;
import android.os.HandlerThread;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationListener;

import java.io.File;
import java.util.Map;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class MainActivity extends Activity {
	private Map<String, ?> map;
	private MainActivity mainActivity;
	private boolean dtrunning = false;
	private DrawTermThread dthread;
	private int notificationId;
	private byte []jpegBytes;
	private String location;

	static {
		System.loadLibrary("drawterm");
	}

	private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

	static {
		ORIENTATIONS.append(Surface.ROTATION_0, 0);
		ORIENTATIONS.append(Surface.ROTATION_90, 90);
		ORIENTATIONS.append(Surface.ROTATION_180, 180);
		ORIENTATIONS.append(Surface.ROTATION_270, 270);
	}

	static class CompareSizesByArea implements Comparator<Size> {
		@Override
		public int compare(Size lhs, Size rhs) {
			return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
		}
	}


	private static boolean contains(int[] modes, int mode) {
		if (modes == null) {
			return false;
		}
		for (int i : modes) {
			if (i == mode) {
				return true;
			}
		}
		return false;
	}

	public String getLocation() {
		LocationManager locationManager = ((LocationManager)getSystemService(Context.LOCATION_SERVICE));

		location = "";

		HandlerThread mBackgroundThread = new HandlerThread("Location Background");
		mBackgroundThread.start();

		locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() {
			@Override
			public void onLocationChanged(Location l) {
				location = l.getLatitude() + "\t" + l.getLongitude() + "\t" + l.getAltitude();
				mBackgroundThread.quitSafely();
			}

			@Override
			public void onProviderDisabled(String p) {
				mBackgroundThread.quitSafely();
			}

			@Override
			public void onProviderEnabled(String p) {
			}

			@Override
			public void onStatusChanged(String p, int i, Bundle b) {
			}
		}, mBackgroundThread.getLooper());

		try {
			mBackgroundThread.join();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return location;
	}

	public void showNotification(String text) {
		Notification.Builder builder = new Notification.Builder(this)
			.setDefaults(Notification.DEFAULT_SOUND)
			.setSmallIcon(R.drawable.ic_small)
			.setContentText(text)
			.setStyle(new Notification.BigTextStyle().bigText(text))
			.setPriority(Notification.PRIORITY_DEFAULT);

		((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId, builder.build());
		notificationId++;
	}

	public int numCameras() {
		try {
			return ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	private static int sensorToDeviceRotation(CameraCharacteristics c, int deviceOrientation) {
		int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);

		deviceOrientation = ORIENTATIONS.get(deviceOrientation);

		if (c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
			deviceOrientation = -deviceOrientation;
		}

		return (sensorOrientation - deviceOrientation + 360) % 360;
	}

	public void takePicture(int id) {
		try {
			jpegBytes = null;
			HandlerThread mBackgroundThread = new HandlerThread("Camera Background");
			mBackgroundThread.start();
			Handler mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
			CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
			String []cameraIdList = manager.getCameraIdList();
			CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIdList[id]);
			StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
			Size size = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizesByArea());
			ImageReader reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), ImageFormat.JPEG, 1);
			manager.openCamera(cameraIdList[id], new CameraDevice.StateCallback() {
				public void onOpened(CameraDevice device) {
					try {
						CaptureRequest.Builder captureBuilder = device.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
						captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
						Float minFocusDist = characteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
						if (!(minFocusDist == null || minFocusDist == 0)) {
							if (contains(characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES), CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE))
								captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
							else 
								captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
						}
						if (contains(characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES), CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH))
							captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
						else
							captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
						if (contains(characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES), CaptureRequest.CONTROL_AWB_MODE_AUTO))
							captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
						captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, sensorToDeviceRotation(characteristics, getWindowManager().getDefaultDisplay().getRotation()));
						captureBuilder.addTarget(reader.getSurface());
						reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
							public void onImageAvailable(ImageReader reader) {
								Image image = null;
								try {
									image = reader.acquireLatestImage();
									ByteBuffer buffer = image.getPlanes()[0].getBuffer();
									jpegBytes = new byte[buffer.capacity()];
									buffer.get(jpegBytes);
								} catch (Exception e) {
									e.printStackTrace();
								} finally {
									if (image != null) {
										image.close();
									}
								}
							}
						}, mBackgroundHandler);
						List<Surface> outputSurfaces = new ArrayList<Surface>(1);
						outputSurfaces.add(reader.getSurface());
						device.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
							public void onConfigured(CameraCaptureSession session) {
								try {
									List<CaptureRequest> captureRequests = new ArrayList<CaptureRequest>(10);
										for (int i = 0; i < 10; i++)
									captureRequests.add(captureBuilder.build());
									session.captureBurst(captureRequests, new CameraCaptureSession.CaptureCallback() {
										public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {
											Log.w("drawterm", "CaptureSession capture sequence completed");
											sendPicture(jpegBytes);
											device.close();
										}
									}, mBackgroundHandler);
								} catch (Exception e) {
									Log.w("drawterm", "CaptureSession capture failed");
									e.printStackTrace();
									sendPicture(jpegBytes);
								}
							}
							public void onConfigureFailed(CameraCaptureSession session) {
								Log.w("drawterm", "createCaptureSession configure failed");
								sendPicture(jpegBytes);
							}
						}, mBackgroundHandler);
					} catch (Exception e) {
						e.printStackTrace();
						sendPicture(jpegBytes);
					}
				}	
				public void onDisconnected(CameraDevice device) {
					try {
						device.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
					Log.e("drawterm", "openCamera onDisconnected");
				}
				public void onError(CameraDevice device, int error) {
					try {
						device.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
					Log.e("drawterm", "openCamera onError " + error);
				}
				public void onClosed(CameraDevice device) {
					try {
						mBackgroundThread.quitSafely();
						mBackgroundThread.join();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}, mBackgroundHandler);
		} catch (Exception e) {
			e.printStackTrace();
			sendPicture(jpegBytes);
		}
	}

	public void serverView(View v) {
		setContentView(R.layout.server_main);
		serverButtons();

		String s = (String)map.get(((TextView)v).getText().toString());
		String []a = s.split("\007");

		((EditText)findViewById(R.id.cpuServer)).setText((String)a[0]);
		((EditText)findViewById(R.id.authServer)).setText((String)a[1]);
		((EditText)findViewById(R.id.userName)).setText((String)a[2]);
		((EditText)findViewById(R.id.passWord)).setText((String)a[3]);

		((CheckBox)findViewById(R.id.aan)).setChecked(((String)a[4]).equals("true") ? true : false);
		((CheckBox)findViewById(R.id.cmd)).setChecked(((String)a[5]).equals("true") ? true : false);
		((CheckBox)findViewById(R.id.root)).setChecked(((String)a[6]).equals("true") ? true : false);
	}

	public void populateServers(Context context) {
		ListView ll = (ListView)findViewById(R.id.servers);
		ArrayAdapter<String> la = new ArrayAdapter<String>(this, R.layout.item_main);
		SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0);
		map = (Map<String, ?>)settings.getAll();
		String key;
		Object []keys = map.keySet().toArray();
		for (int i = 0; i < keys.length; i++) {
			key = (String)keys[i];
			la.add(key);
		}
		ll.setAdapter(la);

		setDTSurface(null);
		dtrunning = false;
	}

	public void runDrawterm(String []args, String pass) {
		Resources res = getResources();
		DisplayMetrics dm = res.getDisplayMetrics();

		int wp = dm.widthPixels;
		int hp = dm.heightPixels;

		setContentView(R.layout.drawterm_main);

		Button kbutton = (Button)findViewById(R.id.keyboardToggle);
		kbutton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(final View view) {
				InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
				imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
			}
		});

		int rid = res.getIdentifier("navigation_bar_height", "dimen", "android");
		if (rid > 0) {
			hp -= res.getDimensionPixelSize(rid);
		}
		LinearLayout ll = (LinearLayout)findViewById(R.id.dtButtons);
		hp -= ll.getHeight();

		int w = (int)(wp * (160.0/dm.xdpi));
		int h = (int)(hp * (160.0/dm.ydpi));
		float ws = (float)wp/w;
		float hs = (float)hp/h;
		// only scale up
		if (ws < 1) {
			ws = 1;
			w = wp;
		}
		if (hs < 1) {
			hs = 1;
			h = hp;
		}

		MySurfaceView mView = new MySurfaceView(mainActivity, w, h, ws, hs);
		mView.getHolder().setFixedSize(w, h);

		LinearLayout l = (LinearLayout)findViewById(R.id.dlayout);
		l.addView(mView, 1, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));

		dthread = new DrawTermThread(args, pass, mainActivity);
		dthread.start();

		dtrunning = true;
	}

	public void serverButtons() {
		Button button = (Button)findViewById(R.id.save);
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString();
				String auth = ((EditText)findViewById(R.id.authServer)).getText().toString();
				String user = ((EditText)findViewById(R.id.userName)).getText().toString();
				String pass = ((EditText)findViewById(R.id.passWord)).getText().toString();
				String aan = ((CheckBox)findViewById(R.id.aan)).isChecked() ? "true" : "false";
				String cmd = ((CheckBox)findViewById(R.id.cmd)).isChecked() ? "true" : "false";
				String root = ((CheckBox)findViewById(R.id.root)).isChecked() ? "true" : "false";

				SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0);
				SharedPreferences.Editor editor = settings.edit();
				editor.putString(user + "@" + cpu + " (auth="  + auth + ")", cpu + "\007" + auth + "\007" + user + "\007" + pass + "\007" + aan + "\007" + cmd + "\007" + root);
				editor.commit();
			}
		});

		button = (Button) findViewById(R.id.connect);
		button.setOnClickListener(new View.OnClickListener() {
			private String[] appendString(String []args, String s) {
				String ret[] = Arrays.copyOf(args, args.length + 1);
				ret[ret.length - 1] = s;
				return ret;
			}

			@Override
			public void onClick(final View view) {
				String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString();
				String auth = ((EditText)findViewById(R.id.authServer)).getText().toString();
				String user = ((EditText)findViewById(R.id.userName)).getText().toString();
				String pass = ((EditText)findViewById(R.id.passWord)).getText().toString();

				String args[] = {"drawterm", "-h", cpu, "-a", auth, "-u", user};
				if (((CheckBox)findViewById(R.id.aan)).isChecked())
					args = appendString(args, "-p");
				if (!((CheckBox)findViewById(R.id.cmd)).isChecked())
					args = appendString(args, "-C");
				if (!((CheckBox)findViewById(R.id.root)).isChecked())
					args = appendString(args, "-R");
				runDrawterm(args, pass);
			}
		});
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		mainActivity = this;
		setObject();
		setContentView(R.layout.activity_main);
		populateServers(this);

		View fab = findViewById(R.id.fab);
		fab.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				setContentView(R.layout.server_main);
				serverButtons();
			}
		});
	}

	@Override
	public boolean dispatchKeyEvent(KeyEvent event)
	{
		if (!dtrunning) {
			return super.dispatchKeyEvent(event);
		}

		int k = event.getUnicodeChar();
		if (k == 0) {
			k = event.getDisplayLabel();
			if (k >= 'A' && k <= 'Z')
				k |= 0x20;
		}
		String chars = event.getCharacters();
		if (k == 0 && chars != null) {
			for (int i = 0; i < chars.length(); i++) {
				k = chars.codePointAt(i);
				keyDown(k);
				keyUp(k);
			}
			return true;
		}

		if (k == 0) switch (event.getKeyCode()) {
		case KeyEvent.KEYCODE_DEL:
			k = 0x0008;
			break;
		case KeyEvent.KEYCODE_FORWARD_DEL:
			k = 0x007F;
			break;
		case KeyEvent.KEYCODE_ESCAPE:
			k = 0x001B;
			break;
		case KeyEvent.KEYCODE_MOVE_HOME:
			k = 0xF00D;
			break;
		case KeyEvent.KEYCODE_MOVE_END:
			k = 0xF018;
			break;
		case KeyEvent.KEYCODE_PAGE_UP:
			k = 0xF00F;
			break;
		case KeyEvent.KEYCODE_PAGE_DOWN:
			k = 0xF013;
			break;
		case KeyEvent.KEYCODE_INSERT:
			k = 0xF014;
			break;
		case KeyEvent.KEYCODE_SYSRQ:
			k = 0xF010;
			break;
		case KeyEvent.KEYCODE_DPAD_UP:
			k = 0xF00E;
			break;
		case KeyEvent.KEYCODE_DPAD_LEFT:
			k = 0xF011;
			break;
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			k = 0xF012;
			break;
		case KeyEvent.KEYCODE_DPAD_DOWN:
			k = 0xF800;
			break;
		}

		if (k == 0)
			return true;

		if (event.isCtrlPressed()) {
			keyDown(0xF017);
		}
		if (event.isAltPressed() && k < 128) {
			keyDown(0xF015);
		}

		if (event.getAction() == KeyEvent.ACTION_DOWN) {
			keyDown(k);
		}
		else if (event.getAction() == KeyEvent.ACTION_UP) {
			keyUp(k);
		}

		if (event.isCtrlPressed()) {
			keyUp(0xF017);
		}
		if (event.isAltPressed() && k < 128) {
			keyUp(0xF015);
		}

		return true;
	}

	@Override
	public void onBackPressed()
	{
	}

	@Override
	public void onDestroy()
	{
		setDTSurface(null);
		dtrunning = false;
		exitDT();
		super.onDestroy();
	}

	public void setClipBoard(String str) {
		ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
		if (cm != null) {
			ClipData cd = ClipData.newPlainText(null, str);
			cm.setPrimaryClip(cd);
		}
	}

	public String getClipBoard() {
		ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
		if (cm != null) {
			ClipData cd = cm.getPrimaryClip();
			if (cd != null)
				return (String)(cd.getItemAt(0).coerceToText(mainActivity.getApplicationContext()).toString());
		}
		return "";
	}

	public native void dtmain(Object[] args);
	public native void setPass(String arg);
	public native void setWidth(int arg);
	public native void setHeight(int arg);
	public native void setWidthScale(float arg);
	public native void setHeightScale(float arg);
	public native void setDTSurface(Surface surface);
	public native void setMouse(int[] args);
	public native void setObject();
	public native void keyDown(int c);
	public native void keyUp(int c);
	public native void exitDT();
	public native void sendPicture(byte[] array);
}