| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- package org.golang.app;
- import android.app.Activity;
- import android.app.NativeActivity;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.ActivityInfo;
- import android.content.pm.PackageManager;
- import android.content.res.Configuration;
- import android.graphics.Rect;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Bundle;
- import android.text.Editable;
- import android.text.InputType;
- import android.text.TextWatcher;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.KeyCharacterMap;
- import android.view.View;
- import android.view.WindowInsets;
- import android.view.inputmethod.EditorInfo;
- import android.view.inputmethod.InputMethodManager;
- import android.view.KeyEvent;
- import android.widget.EditText;
- import android.widget.FrameLayout;
- import android.widget.TextView;
- import android.widget.TextView.OnEditorActionListener;
- public class GoNativeActivity extends NativeActivity {
- private static GoNativeActivity goNativeActivity;
- private static final int FILE_OPEN_CODE = 1;
- private static final int FILE_SAVE_CODE = 2;
- private static final int DEFAULT_INPUT_TYPE = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
- private static final int DEFAULT_KEYBOARD_CODE = 0;
- private static final int SINGLELINE_KEYBOARD_CODE = 1;
- private static final int NUMBER_KEYBOARD_CODE = 2;
- private static final int PASSWORD_KEYBOARD_CODE = 3;
- private native void filePickerReturned(String str);
- private native void insetsChanged(int top, int bottom, int left, int right);
- private native void keyboardTyped(String str);
- private native void keyboardDelete();
- private native void setDarkMode(boolean dark);
- private EditText mTextEdit;
- private boolean ignoreKey = false;
- public GoNativeActivity() {
- super();
- goNativeActivity = this;
- }
- String getTmpdir() {
- return getCacheDir().getAbsolutePath();
- }
- void updateLayout() {
- try {
- WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
- if (insets == null) {
- return;
- }
- insetsChanged(insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetBottom(),
- insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetRight());
- } catch (java.lang.NoSuchMethodError e) {
- Rect insets = new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(insets);
- View view = findViewById(android.R.id.content).getRootView();
- insetsChanged(insets.top, view.getHeight() - insets.height() - insets.top,
- insets.left, view.getWidth() - insets.width() - insets.left);
- }
- }
- static void showKeyboard(int keyboardType) {
- goNativeActivity.doShowKeyboard(keyboardType);
- }
- void doShowKeyboard(final int keyboardType) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- int imeOptions = EditorInfo.IME_FLAG_NO_ENTER_ACTION;
- int inputType = DEFAULT_INPUT_TYPE;
- switch (keyboardType) {
- case DEFAULT_KEYBOARD_CODE:
- imeOptions = EditorInfo.IME_FLAG_NO_ENTER_ACTION;
- break;
- case SINGLELINE_KEYBOARD_CODE:
- imeOptions = EditorInfo.IME_ACTION_DONE;
- break;
- case NUMBER_KEYBOARD_CODE:
- imeOptions = EditorInfo.IME_ACTION_DONE;
- inputType |= InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL;
- break;
- case PASSWORD_KEYBOARD_CODE:
- imeOptions = EditorInfo.IME_ACTION_DONE;
- inputType |= InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
- default:
- Log.e("Fyne", "unknown keyboard type, use default");
- }
- mTextEdit.setImeOptions(imeOptions);
- mTextEdit.setInputType(inputType);
- mTextEdit.setOnEditorActionListener(new OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_ACTION_DONE) {
- keyboardTyped("\n");
- }
- return false;
- }
- });
- // always place one character so all keyboards can send backspace
- ignoreKey = true;
- mTextEdit.setText("0");
- mTextEdit.setSelection(mTextEdit.getText().length());
- ignoreKey = false;
- mTextEdit.setVisibility(View.VISIBLE);
- mTextEdit.bringToFront();
- mTextEdit.requestFocus();
- InputMethodManager m = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- m.showSoftInput(mTextEdit, 0);
- }
- });
- }
- static void hideKeyboard() {
- goNativeActivity.doHideKeyboard();
- }
- void doHideKeyboard() {
- InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- View view = findViewById(android.R.id.content).getRootView();
- imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTextEdit.setVisibility(View.GONE);
- }
- });
- }
- static void showFileOpen(String mimes) {
- goNativeActivity.doShowFileOpen(mimes);
- }
- void doShowFileOpen(String mimes) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- if ("application/x-directory".equals(mimes) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // ask for a directory picker if OS supports it
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- } else if (mimes.contains("|") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- intent.setType("*/*");
- intent.putExtra(Intent.EXTRA_MIME_TYPES, mimes.split("\\|"));
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- } else {
- intent.setType(mimes);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- }
- startActivityForResult(Intent.createChooser(intent, "Open File"), FILE_OPEN_CODE);
- }
- static void showFileSave(String mimes, String filename) {
- goNativeActivity.doShowFileSave(mimes, filename);
- }
- void doShowFileSave(String mimes, String filename) {
- Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- if (mimes.contains("|") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- intent.setType("*/*");
- intent.putExtra(Intent.EXTRA_MIME_TYPES, mimes.split("\\|"));
- } else {
- intent.setType(mimes);
- }
- intent.putExtra(Intent.EXTRA_TITLE, filename);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- startActivityForResult(Intent.createChooser(intent, "Save File"), FILE_SAVE_CODE);
- }
- static int getRune(int deviceId, int keyCode, int metaState) {
- try {
- int rune = KeyCharacterMap.load(deviceId).get(keyCode, metaState);
- if (rune == 0) {
- return -1;
- }
- return rune;
- } catch (KeyCharacterMap.UnavailableException e) {
- return -1;
- } catch (Exception e) {
- Log.e("Fyne", "exception reading KeyCharacterMap", e);
- return -1;
- }
- }
- private void load() {
- // Interestingly, NativeActivity uses a different method
- // to find native code to execute, avoiding
- // System.loadLibrary. The result is Java methods
- // implemented in C with JNIEXPORT (and JNI_OnLoad) are not
- // available unless an explicit call to System.loadLibrary
- // is done. So we do it here, borrowing the name of the
- // library from the same AndroidManifest.xml metadata used
- // by NativeActivity.
- try {
- ActivityInfo ai = getPackageManager().getActivityInfo(
- getIntent().getComponent(), PackageManager.GET_META_DATA);
- if (ai.metaData == null) {
- Log.e("Fyne", "loadLibrary: no manifest metadata found");
- return;
- }
- String libName = ai.metaData.getString("android.app.lib_name");
- System.loadLibrary(libName);
- } catch (Exception e) {
- Log.e("Fyne", "loadLibrary failed", e);
- }
- }
- @Override
- public void onCreate(Bundle savedInstanceState) {
- load();
- super.onCreate(savedInstanceState);
- setupEntry();
- updateTheme(getResources().getConfiguration());
- View view = findViewById(android.R.id.content).getRootView();
- view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- public void onLayoutChange (View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- GoNativeActivity.this.updateLayout();
- }
- });
- }
- private void setupEntry() {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTextEdit = new EditText(goNativeActivity);
- mTextEdit.setVisibility(View.GONE);
- mTextEdit.setInputType(DEFAULT_INPUT_TYPE);
- FrameLayout.LayoutParams mEditTextLayoutParams = new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
- mTextEdit.setLayoutParams(mEditTextLayoutParams);
- addContentView(mTextEdit, mEditTextLayoutParams);
- // always place one character so all keyboards can send backspace
- mTextEdit.setText("0");
- mTextEdit.setSelection(mTextEdit.getText().length());
- mTextEdit.addTextChangedListener(new TextWatcher() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (ignoreKey) {
- return;
- }
- if (count > 0) {
- keyboardTyped(s.subSequence(start,start+count).toString());
- }
- }
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- if (ignoreKey) {
- return;
- }
- if (count > 0) {
- for (int i = 0; i < count; i++) {
- // send a backspace
- keyboardDelete();
- }
- }
- }
- @Override
- public void afterTextChanged(Editable s) {
- // always place one character so all keyboards can send backspace
- if (s.length() < 1) {
- ignoreKey = true;
- mTextEdit.setText("0");
- mTextEdit.setSelection(mTextEdit.getText().length());
- ignoreKey = false;
- return;
- }
- }
- });
- }
- });
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // unhandled request
- if (requestCode != FILE_OPEN_CODE && requestCode != FILE_SAVE_CODE) {
- return;
- }
- // dialog was cancelled
- if (resultCode != Activity.RESULT_OK) {
- filePickerReturned("");
- return;
- }
- Uri uri = data.getData();
- filePickerReturned(uri.toString());
- }
- @Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- updateTheme(config);
- }
- protected void updateTheme(Configuration config) {
- boolean dark = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
- setDarkMode(dark);
- }
- }
|