Compare commits

...

20 Commits

Author SHA1 Message Date
Yuriy Liskov
b2d8ce5aab readme 2019-03-22 18:39:54 +02:00
Yuriy Liskov
7dfaac0683 gradle upd 2019-02-25 01:20:30 +02:00
Yuriy Liskov
cc3f605970 update readme 2018-11-29 22:47:17 +02:00
Yuriy Liskov
ac637c79f4 add telegram link 2018-11-29 22:37:01 +02:00
Yuriy Liskov
cb13108a11 fix: home activity not found: update 2 2018-09-18 00:37:14 +03:00
Yuriy Liskov
43ef8324bf fix: home activity not found 2018-09-17 03:33:41 +03:00
Yuriy Liskov
70cfd73ac8 mouse pointer animation fix: update 2 2018-09-17 02:41:00 +03:00
Yuriy Liskov
0a42892d2d mouse pointer animation fix 2018-09-17 01:59:05 +03:00
Yuriy Liskov
c5c88e622d bit refactor 2018-09-17 01:25:26 +03:00
Yuriy Liskov
6e7db94a30 fix issue #7 2018-09-15 03:27:45 +03:00
Yuriy Liskov
80b76e9d1e donation 2018-09-08 00:08:58 +03:00
Yuriy Liskov
8c1c36cf0e update readme 2018-09-04 16:32:26 +03:00
Yuriy Liskov
a4d615bbf2 persian fix 2018-08-29 15:59:25 +03:00
Yuriy Liskov
5e8e68de44 persian fix; enter in editor fix 2018-08-20 16:05:06 +03:00
Yuriy Liskov
48e12a21d1 ESC fix #2 2018-08-10 18:42:20 +03:00
Yuriy Liskov
6a8b9c63e5 ESC and Go fixes (see github > issues) 2018-08-07 20:39:07 +03:00
Yuriy Liskov
95ab858296 bugfixes 2018-08-04 18:19:57 +03:00
Yuriy Liskov
37243e4d11 hide soft kbd on physical key 2018-08-03 19:00:34 +03:00
Yuriy Liskov
0c7052be55 Swedish translate fix 2018-07-19 00:02:24 +03:00
Yuriy Liskov
5bf9563011 Swedish translate fix 2018-07-18 22:25:27 +03:00
17 changed files with 370 additions and 181 deletions

View File

@@ -5,8 +5,8 @@
__LeanKeyKeyboard: Keyboard for Android-based set-top boxes and TVs:__
Visit Google Play page:
* <a href="https://play.google.com/store/apps/details?id=org.liskovsoft.androidtv.rukeyboard" target="_blank">[APP] LeanKeyKeyboard</a>
* <a href="https://t.me/LeanKeyKeyboard">Telegram group</a>
* <a href="https://play.google.com/store/apps/details?id=org.liskovsoft.androidtv.rukeyboard" target="_blank">Google Play page</a>
__NOTE: Google Play release is outdated. So I recommend to obtain new releases [here](https://github.com/yuliskov/LeanKeyKeyboard/releases).__
@@ -17,7 +17,9 @@ __NOTE: Google Play release is outdated. So I recommend to obtain new releases [
* Doesn't depend on Google Services.
* __No root required!__
__Switch to other language performed with 'world' button, menu key or long press on the space bar.__
__Tip: Switch to other language with language button or by long press on the space bar__
__Tip: Do long press on the language button to choose between available languages__
### Screenshots:
* __[Open screenshots](#screens)__
@@ -31,9 +33,15 @@ __Standard installation via ADB__
* <a href="https://github.com/yuliskov/LeanKeyKeyboard/releases" target="_blank">Download latest LeanKeyKeyboard APK</a> and sideload/install with adb:
* *adb install -r LeanKeyKeyboard.apk*
* Enjoy :)
### Donation:
If you want to support my developments you are welcome to buy me a cup of coffee :)
* [__Donation Alerts (RU)__](https://www.donationalerts.ru/r/firsthash)
* [__PrivatBank (UA)__](https://privatbank.ua/ru/sendmoney?payment=73ab18516e24ad365808eec66192e756879dde16)
* __BTC__: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
### Reviews / Articles:
* Just google for "LeanKey Keyboard"
* [__XDA Discussion__](https://forum.xda-developers.com/fire-tv/general/guide-change-screen-keyboard-to-leankey-t3527675)
### Changelog:
* [Check releases page for changelog ..](https://github.com/yuliskov/LeanKeyKeyboard/releases)
@@ -45,12 +53,6 @@ __Standard installation via ADB__
### Developer:
* __[yuliskov](https://github.com/yuliskov)__ (design & coding)
### Donation:
If you want to support my developments you are welcome to buy me a cup of coffee :)
* BTC: 1JAT5VVWarVBkpVbNDn8UA8HXNdrukuBSx
* WMZ: Z375157140784
* WMU: U449339012933
### Screens:
![Screenshot of LeanKeyKeyboard](img/leankeykeyboard_screenshot_01.png "Screenshot of LeanKeyKeyboard")
![Screenshot of LeanKeyKeyboard](img/leankeykeyboard_screenshot_02.png "Screenshot of LeanKeyKeyboard")

View File

@@ -14,14 +14,14 @@ buildscript {
// https://stackoverflow.com/questions/20404476/how-to-define-common-android-properties-for-all-modules-using-gradle
// Gradle constants example: https://github.com/google/ExoPlayer
ext {
compileSdkVersion = 26
buildToolsVersion = "26.0.2"
compileSdkVersion = 28
buildToolsVersion = "28.0.3"
minSdkVersion = 14
targetSdkVersion = 26
appCompatVersion = 'com.android.support:appcompat-v7:26.+'
appCompatVersion = 'com.android.support:appcompat-v7:28.+'
espressoCoreVersion = 'com.android.support.test.espresso:espresso-core:2.2.2'
junitVersion = 'junit:junit:4.12'
supportVersion = 'com.android.support:support-v4:26.+'
supportVersion = 'com.android.support:support-v4:28.+'
robolectricVersion = 'org.robolectric:robolectric:3.5.1'
crashlyticsVersion = 'com.crashlytics.sdk.android:crashlytics:2.8.0@aar'
}

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.liskovsoft.leankeykeyboard.pro"
minSdkVersion project.properties.minSdkVersion
targetSdkVersion project.properties.targetSdkVersion
versionCode 68
versionName "4.3.18"
versionCode 80
versionName "4.3.30"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

View File

@@ -5,16 +5,23 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<application android:banner="@drawable/banner_app" android:label="@string/ime_name" android:icon="@drawable/ic_launcher" tools:targetApi="21">
<activity android:launchMode="singleTop" android:name="com.liskovsoft.other.SettingsActivity">
<activity android:launchMode="singleTop" android:name="com.liskovsoft.other.GenericLaunchActivity">
<meta-data android:name="package" android:value="com.android.settings"/>
<meta-data android:name="class" android:value="com.android.settings.Settings$InputMethodAndLanguageSettingsActivity"/>
<meta-data android:name="class" android:value="com.android.settings.Settings$LanguageAndInputSettingsActivity"/>
<!-- "Languages & input" on old api -->
<meta-data android:name="package_alt" android:value="com.android.settings"/>
<meta-data android:name="class_alt" android:value="com.android.settings.Settings$InputMethodAndLanguageSettingsActivity"/>
<!-- Last try (if above not found) -->
<meta-data android:name="intent" android:value="android.settings.INPUT_METHOD_SETTINGS"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
<service android:label="@string/ime_service_name" android:name="com.google.leanback.ime.LeanbackImeService" android:permission="android.permission.BIND_INPUT_METHOD">
<service android:label="@string/ime_service_name"
android:name="com.google.leanback.ime.LeanbackImeService"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>

View File

@@ -320,10 +320,10 @@ public class LeanbackKeyboardContainer {
* Init currently displayed keyboard<br/>
* Note: all keyboard settings applied here<br/>
* Note: this method is called constantly on new field
* @param resources resources (not used)
* @param res resources (not used)
* @param info current ime attributes
*/
private void setImeOptions(Resources resources, EditorInfo info) {
private void setImeOptions(Resources res, EditorInfo info) {
// do not erase last keyboard
if (mInitialMainKeyboard == null) {
mInitialMainKeyboard = mAbcKeyboard;
@@ -446,23 +446,23 @@ public class LeanbackKeyboardContainer {
boolean overestimateHeight = false;
switch (focus.type) {
case KeyFocus.TYPE_MAIN:
boolean showScale = false;
overestimateHeight = true;
if (focus.code != LeanbackKeyboardView.ASCII_SPACE) {
overestimateWidth = true;
} else {
overestimateWidth = false;
showScale = true;
}
LeanbackKeyboardView mainView = mMainKeyboardView;
int index = focus.index;
boolean isClicked = false;
if (mTouchState == TOUCH_STATE_CLICK) {
overestimateHeight = true;
} else {
overestimateHeight = false;
isClicked = true;
}
mainView.setFocus(index, overestimateHeight, overestimateWidth);
mainView.setFocus(index, isClicked, showScale);
mPrevView = mMainKeyboardView;
overestimateHeight = true;
break;
case KeyFocus.TYPE_VOICE:
mVoiceButtonView.setMicFocused(true);
@@ -594,7 +594,12 @@ public class LeanbackKeyboardContainer {
mSelector.setX(translatedX);
mSelector.setY(translatedY);
} else {
mSelector.animate().x(translatedX).y(translatedY).setInterpolator(sMovementInterpolator).setDuration(MOVEMENT_ANIMATION_DURATION).start();
mSelector.animate()
.x(translatedX)
.y(translatedY)
.setInterpolator(sMovementInterpolator)
.setDuration(MOVEMENT_ANIMATION_DURATION)
.start();
}
}
@@ -853,7 +858,7 @@ public class LeanbackKeyboardContainer {
}
public boolean isVoiceVisible() {
return mVoiceButtonView.getVisibility() == 0;
return mVoiceButtonView.getVisibility() == View.VISIBLE;
}
public void onInitInputView() {
@@ -1031,6 +1036,10 @@ public class LeanbackKeyboardContainer {
setKbFocus(focus, false, true);
}
public void setFocus(LeanbackKeyboardContainer.KeyFocus focus, final boolean animate) {
setKbFocus(focus, false, animate);
}
public void setSelectorToFocus(Rect rect, boolean overestimateWidth, boolean overestimateHeight, boolean animate) {
if (this.mSelector.getWidth() != 0 && this.mSelector.getHeight() != 0 && rect.width() != 0 && rect.height() != 0) {
final float width = (float) rect.width();
@@ -1132,7 +1141,7 @@ public class LeanbackKeyboardContainer {
}
public void updateAddonKeyboard() {
mKeyboardManager = new KeyboardManager(mContext, mAbcKeyboard);
mKeyboardManager = new KeyboardManager(mContext);
switchToNextKeyboard();
}

View File

@@ -1,10 +1,10 @@
package com.google.android.leanback.ime;
import android.graphics.PointF;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard.Key;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
@@ -30,6 +30,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private static final int KEY_CHANGE_HISTORY_SIZE = 10;
private static final long KEY_CHANGE_REVERT_TIME_MS = 100L;
private static final String TAG = "LbKbController";
public static final String TAG_GO = "Go";
private boolean clickConsumed;
private long lastClickTime;
private LeanbackKeyboardContainer mContainer;
@@ -49,8 +50,10 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private LeanbackKeyboardContainer.KeyFocus mTempFocus;
private PointF mTempPoint;
private LeanbackKeyboardController.TouchEventListener mTouchEventListener;
private long prevTime;
private long mPrevTime;
private boolean mShowInput;
private int mLastEditorIdPhysicalKeyboardWasUsed;
private boolean mHideKeyboardWhenPhysicalKeyboardUsed = true;
public LeanbackKeyboardController(final InputMethodService context, final LeanbackKeyboardController.InputListener listener) {
this(context, listener, new TouchNavSpaceTracker(), new LeanbackKeyboardContainer(context));
@@ -151,14 +154,19 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
this.commitKey(this.mContainer.getCurrFocus());
}
/**
* NOTE: where all magic happens. Input from virtual kbd is processed here.
* @param focus current key
*/
private void commitKey(LeanbackKeyboardContainer.KeyFocus focus) {
if (mContainer != null && focus != null) {
switch (focus.type) {
case KeyFocus.TYPE_VOICE:
mContainer.onVoiceClick();
return;
case KeyFocus.TYPE_ACTION:
case KeyFocus.TYPE_ACTION: // NOTE: user presses Go, Send, Search etc
mInputListener.onEntry(InputListener.ENTRY_TYPE_ACTION, 0, null);
// mContext.hideWindow(); // SmartYouTubeTV fix: force hide keyboard
return;
case KeyFocus.TYPE_SUGGESTION:
mInputListener.onEntry(InputListener.ENTRY_TYPE_SUGGESTION, 0, mContainer.getSuggestionText(focus.index));
@@ -434,7 +442,8 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
private boolean handleKeyUpEvent(int keyCode, long currTime) {
keyCode = getSimplifiedKey(keyCode);
boolean handled;
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
handled = false;
} else if (mContainer.isVoiceVisible()) {
handled = true;
@@ -490,15 +499,39 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
updatePositionToCurrentFocus();
}
private boolean isCallAllowed(int periodMillis) {
/**
* Simple throttle routine.
* @param callInterval interval
* @return is allowed
*/
private boolean isCallAllowedOrigin(int callInterval) {
long currTimeMS = System.currentTimeMillis();
if (this.prevTime != 0L && currTimeMS - this.prevTime <= (long) (periodMillis * 3)) {
if (currTimeMS - this.prevTime > (long) periodMillis) {
this.prevTime = 0L;
long timeDelta = currTimeMS - mPrevTime;
if (mPrevTime != 0 && timeDelta <= (callInterval * 3)) {
if (timeDelta > callInterval) {
mPrevTime = 0;
return true;
}
} else {
this.prevTime = currTimeMS;
mPrevTime = currTimeMS;
}
return false;
}
/**
* Simple throttle routine. Simplified comparing to previous. Not tested yet!!!!
* @param interval interval
* @return is allowed
*/
private boolean isCallAllowed2(int interval) {
long currTimeMS = System.currentTimeMillis();
long timeDelta = currTimeMS - mPrevTime;
if (mPrevTime == 0) {
mPrevTime = currTimeMS;
return true;
} else if (timeDelta > interval) {
mPrevTime = 0;
}
return false;
@@ -530,13 +563,10 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
}
private void moveSelectorToPoint(float x, float y) {
LeanbackKeyboardContainer container = this.mContainer;
LeanbackKeyboardContainer.KeyFocus focus = this.mTempFocus;
container.getBestFocus(new Float(x), new Float(y), focus);
this.mContainer.setFocus(this.mTempFocus);
container = this.mContainer;
Rect rect = this.mTempFocus.rect;
container.alignSelector((float) rect.centerX(), (float) rect.centerY(), false);
LeanbackKeyboardContainer container = mContainer;
LeanbackKeyboardContainer.KeyFocus focus = mTempFocus;
container.getBestFocus(x, y, focus);
mContainer.setFocus(mTempFocus, false);
}
private boolean onDirectionalMove(int dir) {
@@ -604,7 +634,7 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
Button button = mContainer.getGoButton();
button.setOnTouchListener(this);
button.setOnHoverListener(this);
button.setTag("Go");
button.setTag(TAG_GO);
return view;
} else {
return null;
@@ -624,21 +654,21 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
}
/**
* Try to handle on hover event
* Control keyboard from the mouse. Movement catching
* @param view active view
* @param event event object
* @return is hover handled
*/
@Override
public boolean onHover(View view, MotionEvent event) {
boolean allowed = isCallAllowed(300);
if (allowed) {
if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
PointF pos = getRelativePosition(mContainer.getView(), event);
moveSelectorToPoint(pos.x, pos.y);
}
boolean handled = false;
if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
PointF pos = getRelativePosition(mContainer.getView(), event);
moveSelectorToPoint(pos.x, pos.y);
handled = true;
}
return allowed;
return handled;
}
/**
@@ -647,7 +677,12 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
* @param event {@link KeyEvent KeyEvent}
* @return is event handled
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
//greater than zero means it is a physical keyboard.
//we also want to hide the view if it's a glyph (for example, not physical volume-up key)
//if (event.getDeviceId() > 0 && event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
if (event.isPrintingKey()) onPhysicalKeyboardKeyPressed();
mDownFocus.set(mContainer.getCurrFocus());
if (mSpaceTracker != null && mSpaceTracker.onKeyDown(keyCode, event)) {
return true;
@@ -663,6 +698,24 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
}
}
private void onPhysicalKeyboardKeyPressed() {
EditorInfo editorInfo = mContext.getCurrentInputEditorInfo();
mLastEditorIdPhysicalKeyboardWasUsed = editorInfo == null ? 0 : editorInfo.fieldId;
if (mHideKeyboardWhenPhysicalKeyboardUsed) {
mContext.hideWindow();
}
// For all other keys, if we want to do transformations on
// text being entered with a hard keyboard, we need to process
// it and do the appropriate action.
// using physical keyboard is more annoying with candidate view in
// the way
// so we disable it.
// stopping any soft-keyboard prediction
//abortCorrectionAndResetPredictionState(false);
}
public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
if (mSpaceTracker != null && mSpaceTracker.onKeyUp(keyCode, keyEvent)) {
return true;
@@ -718,31 +771,37 @@ public class LeanbackKeyboardController implements LeanbackKeyboardContainer.Voi
@Override
public boolean onTouch(View view, MotionEvent event) {
Object tag = view.getTag();
if (tag != null && "Go".equals(tag)) {
fakeKeyIndex(0, KeyFocus.TYPE_ACTION);
} else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
moveSelectorToPoint(event.getX(), event.getY());
fakeClickDown();
beginLongClickCountdown();
boolean isEnterKey = TAG_GO.equals(tag);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isEnterKey) {
break;
case MotionEvent.ACTION_UP:
if (!clickConsumed) {
clickConsumed = true;
if (isDoubleClick()) {
mContainer.onKeyLongPress();
break;
}
}
fakeClickUp();
moveSelectorToPoint(event.getX(), event.getY());
fakeClickDown();
beginLongClickCountdown();
break;
case MotionEvent.ACTION_UP:
if (isEnterKey) {
fakeKeyIndex(0, KeyFocus.TYPE_ACTION);
break;
}
if (!clickConsumed) {
clickConsumed = true;
if (isDoubleClick()) {
mContainer.onKeyLongPress();
break;
}
fakeLongClickUp();
break;
default:
return false;
}
fakeClickUp();
}
fakeLongClickUp();
break;
default:
return false;
}
return true;

View File

@@ -523,8 +523,12 @@ public class LeanbackKeyboardView extends FrameLayout {
}
mCurrentFocusView = mKeyImageViews[indexFull];
mCurrentFocusView.animate().scaleX(scale).scaleY(scale).setInterpolator(LeanbackKeyboardContainer.sMovementInterpolator)
.setDuration((long) mClickAnimDur).start();
mCurrentFocusView.animate()
.scaleX(scale)
.scaleY(scale)
.setInterpolator(LeanbackKeyboardContainer.sMovementInterpolator)
.setDuration((long) mClickAnimDur)
.start();
}
mFocusIndex = indexFull;

View File

@@ -1,6 +1,7 @@
package com.google.leanback.ime;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.os.Handler;
@@ -161,8 +162,15 @@ public class LeanbackImeService extends InputMethodService {
connection.commitText(text, 1);
mEnterSpaceBeforeCommitting = true;
case InputListener.ENTRY_TYPE_ACTION:
sendDefaultEditorAction(false);
case InputListener.ENTRY_TYPE_ACTION: // NOTE: user presses Go, Send, Search etc
boolean result = sendDefaultEditorAction(true);
if (result) {
hideWindow(); // NOTE: SmartYouTubeTV hide kbd on search page fix
} else {
sendEnterKey(connection);
}
updateSuggestions = false;
break;
case InputListener.ENTRY_TYPE_LEFT:
@@ -210,6 +218,10 @@ public class LeanbackImeService extends InputMethodService {
}
}
private void sendEnterKey(InputConnection connection) {
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
}
@Override
public View onCreateInputView() {
mInputView = mKeyboardController.getView();
@@ -271,14 +283,39 @@ public class LeanbackImeService extends InputMethodService {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// NOTE: hide keyboard on ESC key
// https://github.com/yuliskov/SmartYouTubeTV/issues/142
event = mapEscToBack(event);
keyCode = mapEscToBack(keyCode);
return isInputViewShown() && mKeyboardController.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// NOTE: hide keyboard on ESC key
// https://github.com/yuliskov/SmartYouTubeTV/issues/142
event = mapEscToBack(event);
keyCode = mapEscToBack(keyCode);
return isInputViewShown() && mKeyboardController.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
}
private KeyEvent mapEscToBack(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE) {
// pay attention, you must pass the same action
event = new KeyEvent(event.getAction(), KeyEvent.KEYCODE_BACK);
}
return event;
}
private int mapEscToBack(int keyCode) {
if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
keyCode = KeyEvent.KEYCODE_BACK;
}
return keyCode;
}
// FireTV fix
//@Override
//public boolean onShowInputRequested(int flags, boolean configChange) {
@@ -298,7 +335,7 @@ public class LeanbackImeService extends InputMethodService {
}
}
return 1;
return Service.START_STICKY;
}
@Override

View File

@@ -8,7 +8,6 @@ import java.util.ArrayList;
import java.util.List;
public class KeyboardManager {
private final Keyboard mEnglishKeyboard;
private final Context mContext;
private final KeyboardStateManager mStateManager;
private List<? extends KeyboardBuilder> mKeyboardBuilders;
@@ -17,13 +16,8 @@ public class KeyboardManager {
private int mKeyboardIndex = 0;
public KeyboardManager(Context ctx, int keyboardResId) {
this(ctx, new Keyboard(ctx, keyboardResId));
}
public KeyboardManager(Context ctx, Keyboard englishKeyboard) {
public KeyboardManager(Context ctx) {
mContext = ctx;
mEnglishKeyboard = englishKeyboard;
mStateManager = new KeyboardStateManager(mContext, this);
mStateManager.restore();
init();
@@ -37,7 +31,6 @@ public class KeyboardManager {
private List<Keyboard> buildAllKeyboards() {
List<Keyboard> keyboards = new ArrayList<>();
keyboards.add(mEnglishKeyboard);
if (!mKeyboardBuilders.isEmpty()) {
for (KeyboardBuilder builder : mKeyboardBuilders) {
keyboards.add(builder.createKeyboard());

View File

@@ -21,26 +21,37 @@ public class ResKeyboardFactory implements KeyboardFactory {
@Override
public List<? extends KeyboardBuilder> getAllAvailableKeyboards(Context context) {
List<KeyboardBuilder> result = new ArrayList<>();
List<KeyboardInfo> infos = ResKeyboardInfo.getAllKeyboardInfos(context);
final Resources resources = mContext.getResources();
for (final KeyboardInfo info : infos) {
if (!info.isEnabled()) {
continue;
}
result.add(new KeyboardBuilder() {
@Nullable
@Override
public Keyboard createKeyboard() {
return new Keyboard(mContext, resources.getIdentifier("qwerty_" + info.getLangCode(), "xml", mContext.getPackageName()));
}
});
result.add(createKeyboard(info.getLangCode()));
}
// at least one kbd should be enabled
if (result.isEmpty()) {
KeyboardInfo firstKbd = infos.get(0);
result.add(createKeyboard(firstKbd.getLangCode()));
firstKbd.setEnabled(true);
ResKeyboardInfo.updateAllKeyboardInfos(mContext, infos);
}
return result;
}
private KeyboardBuilder createKeyboard(final String langCode) {
return new KeyboardBuilder() {
@Nullable
@Override
public Keyboard createKeyboard() {
return new Keyboard(mContext, mContext.getResources().getIdentifier("qwerty_" + langCode, "xml", mContext.getPackageName()));
}
};
}
@Override
public boolean needUpdate() {
return ResKeyboardInfo.needUpdate();

View File

@@ -0,0 +1,130 @@
package com.liskovsoft.other;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.pm.PackageManager;
import android.widget.Toast;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ActivityInfo;
import android.content.Intent;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
public class GenericLaunchActivity extends Activity
{
private static final String META_PACKAGE_NAME = "package";
private static final String META_CLASS_NAME = "class";
private static final String META_PACKAGE_NAME_ALT = "package_alt";
private static final String META_CLASS_NAME_ALT = "class_alt";
private static final String META_INTENT_NAME = "intent";
private List<Intent> mIntents = new ArrayList<>();
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
launchApp();
}
@SuppressLint("WrongConstant")
private void addCommonIntentFlags(final Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
@SuppressLint("WrongConstant")
private ActivityInfo getCurrentActivityInfo() {
try {
return getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA | PackageManager.GET_ACTIVITIES);
}
catch (NameNotFoundException ex) {
ex.printStackTrace();
makeLongToast(ex.getLocalizedMessage());
return null;
}
}
private void launchApp() {
makeIntentList();
startIntents();
finish();
}
private void startIntents() {
for (Intent intent : mIntents) {
boolean result = startIntent(intent);
if (result) { // run until first successful attempt
break;
}
}
}
private void makeIntentList() {
final ActivityInfo activityInfo = getCurrentActivityInfo();
if (activityInfo == null) {
return;
}
final Bundle metaData = activityInfo.metaData;
String metaPackageName = metaData.getString(META_PACKAGE_NAME);
String metaClassName = metaData.getString(META_CLASS_NAME);
mIntents.add(createIntent(metaPackageName, metaClassName));
String metaPackageNameAlt = metaData.getString(META_PACKAGE_NAME_ALT);
String metaClassNameAlt = metaData.getString(META_CLASS_NAME_ALT);
mIntents.add(createIntent(metaPackageNameAlt, metaClassNameAlt));
String metaIntentName = metaData.getString(META_INTENT_NAME);
mIntents.add(createIntent(metaIntentName));
}
private Intent createIntent(String intentName) {
if (intentName == null) {
return null;
}
final Intent intent = new Intent();
intent.setAction(intentName);
addCommonIntentFlags(intent);
return intent;
}
private Intent createIntent(String packageName, String className) {
if (packageName == null || className == null) {
return null;
}
final Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, className));
addCommonIntentFlags(intent);
return intent;
}
private void makeLongToast(final String s) {
makeLongToast(s, 10);
}
private void makeLongToast(final String s, int nums) {
int n;
for (n = nums / 2, nums = 0; nums < n; ++nums) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
private boolean startIntent(final Intent intent) {
if (intent == null) {
return false;
}
try {
startActivity(intent);
}
catch (ActivityNotFoundException ex) {
return false;
}
return true;
}
}

View File

@@ -1,77 +0,0 @@
//
// Decompiled by Procyon v0.5.30
//
package com.liskovsoft.other;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.pm.PackageManager;
import android.widget.Toast;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ActivityInfo;
import android.content.Intent;
import android.app.Activity;
public class SettingsActivity extends Activity
{
@SuppressLint("WrongConstant")
private void addIntentFlags(final Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
@SuppressLint("WrongConstant")
private ActivityInfo getCurrentActivityInfo() {
try {
return getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA | PackageManager.GET_ACTIVITIES);
}
catch (NameNotFoundException ex) {
ex.printStackTrace();
makeLongToast(ex.getLocalizedMessage(), 10);
return null;
}
}
private void launchApp() {
final Intent intent = makeIntent(getCurrentActivityInfo());
addIntentFlags(intent);
startIntent(intent);
finish();
}
private Intent makeIntent(final ActivityInfo activityInfo) {
final Bundle metaData = activityInfo.metaData;
final Intent intent = new Intent();
if (metaData.getString("intent") != null) {
intent.setAction(metaData.getString("intent"));
return intent;
}
intent.setComponent(new ComponentName(metaData.getString("package"), metaData.getString("class")));
return intent;
}
private void makeLongToast(final String s, int nums) {
int n;
for (n = nums / 2, nums = 0; nums < n; ++nums) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
private void startIntent(final Intent intent) {
try {
startActivity(intent);
}
catch (ActivityNotFoundException ex) {
ex.printStackTrace();
makeLongToast(ex.getLocalizedMessage(), 10);
}
}
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
launchApp();
}
}

View File

@@ -20,4 +20,6 @@
<string name="keyboardview_keycode_right">Стрелка вправо</string>
<string name="keyboard_headset_required_to_hear_password">Подключите гарнитуру, чтобы услышать пароль.</string>
<string name="keyboard_password_character_no_headset">Точка</string>
<string name="language_dialog_title">Выберите дополнительные раскладки</string>
<string name="language_dialog_subtitle">Чтобы открыть этот диалог, зажмите кнопку \'земной шар\'</string>
</resources>

View File

@@ -2,12 +2,12 @@
<resources>
<string name="ime_name">Tangentbord för Leanback</string>
<string name="ime_service_name">Tangentbord för Leanback</string>
<string name="label_go_key">OK</string>
<string name="label_go_key">Kör</string>
<string name="label_next_key">Nästa</string>
<string name="label_send_key">Skicka</string>
<string name="label_search_key">Sök</string>
<string name="label_done_key">Klar</string>
<string name="settings_title">Tangentbordsalternativ</string>
<string name="settings_title">Tangentbordsinställningar</string>
<string name="title_movement_sensitivity">Rörelsekänslighet</string>
<string name="btn_on"></string>
<string name="btn_off">Av</string>
@@ -20,4 +20,7 @@
<string name="keyboardview_keycode_right">Höger</string>
<string name="keyboard_headset_required_to_hear_password">Anslut hörlurar om du vill höra lösenordet tecken för tecken.</string>
<string name="keyboard_password_character_no_headset">Punkt.</string>
<string name="keyboardview_keycode_lang">Språk</string>
<string name="language_dialog_title">Välj layouter</string>
<string name="language_dialog_subtitle">"För att öppna dialogen nästa gång, tryck länge på knappen med världsikonen</string>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="additional_languages">
<item>Swedish|sv</item>
<item>English|us</item>
<item>Arabic|ar</item>
<item>Bulgarian|bg</item>
<item>Dutch|nl</item>
@@ -13,6 +13,7 @@
<item>Italian|it</item>
<item>Persian|fa</item>
<item>Russian|ru</item>
<item>Swedish|sv</item>
<item>Thai|th</item>
<item>Turkish|tr</item>
<item>Ukrainian|uk</item>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard android:keyWidth="@dimen/key_width" android:keyHeight="@dimen/key_height" android:horizontalGap="@dimen/keyboard_horizontal_gap" android:verticalGap="@dimen/keyboard_vertical_gap"
xmlns:android="http://schemas.android.com/apk/res/android">
<Row>
<Key android:keyLabel="آ" />
</Row>
</Keyboard>

View File

@@ -37,7 +37,8 @@
<Key android:keyLabel="ی" />
<Key android:keyLabel="ب" />
<Key android:keyLabel="ل" />
<Key android:keyLabel="ا" />
<!-- fix from Shobair Mohammadi <shobairmohammadi@gmail.com> -->
<Key android:keyLabel="ا|آ" android:popupKeyboard="@xml/accent_fa_a" />
<Key android:keyLabel="ت" />
<Key android:keyLabel="ن" />
<Key android:keyLabel="م" />