Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0f0445d
- Include grade-wrapper.jar so that we can compile using gradlew
Jan 17, 2026
eee6140
res/org.pocketworkstation.pckeyboard => res-auto
Jan 17, 2026
6f974e7
Appcompat dependency that is compatible with our new Sdk level
Jan 17, 2026
34c04c7
NamespaceTypo: ignore, because we are deliberately defining a new nam…
Jan 17, 2026
5fe1504
WrongCall: Do not call onDraw() callback from local, but instead defi…
Jan 17, 2026
8a957a2
LongLogTag: shorten log tag
Jan 17, 2026
8dc9929
Measurements, config items, versions and strings labeled as English n…
Jan 17, 2026
6db90a1
ignore legitimately missing translations for now, this should not be …
Jan 17, 2026
85b27ad
Ignore ExtraTranslation for now: not pretty, but no reason why this s…
Jan 17, 2026
64dd19c
Use targetSdkVersion 30
Jan 17, 2026
ad8aa8a
Add "queries" for lookups of dictionary applications
Jan 17, 2026
b874b89
Most recent appcompat that we can use with Sdk level 30
Jan 17, 2026
c3d5226
Upgrade to gradle 8.x
Jan 17, 2026
217dfb1
Add ExpiredTargetSdkVersion to lint.xml: allow us to upgrade gradle a…
Jan 17, 2026
f997bcc
Newer junit
Jan 17, 2026
e879bb7
Sdk level 34
Jan 17, 2026
ece7598
Move to appcompat 1.6.1
Jan 17, 2026
61d2c0c
Use ContextCompat to simplify
Jan 17, 2026
6359225
Need FLAG_ACTIVITY_NEW_TASK when starting activity from a service
Jan 17, 2026
576186e
Properly fix NamespaceTypo issue
Jan 17, 2026
11337df
Broadcast receivers need FLAG_ACTIVITY_NEW_TASK too
Jan 17, 2026
852a23d
SdkVersion 36
Jan 17, 2026
0cde105
Upgrade gradle to 8.14.3
Jan 17, 2026
816885a
No need to repeat package name in AndroidManifest.xml
Jan 17, 2026
27114c5
Fixed 2 minor warnings
Jan 17, 2026
c2f6eaf
Unused namespace
Jan 17, 2026
9a7dd9a
We're done with Sdk, no longer needed to ignore Sdk mismatches
Jan 17, 2026
b0ac3ef
Add android:fitsSystemWindows="true" to make sure top of window is vi…
Jan 18, 2026
6a86e96
Go back to Sdk, keyboard itself slips behind navbar.
Jan 18, 2026
81457ca
Keyboard layouts are just layouts like any other, and understand fits…
Jan 19, 2026
a64d9ab
Have to go back again to Sdk 34 due to keyboard width in landscape mo…
Jan 20, 2026
0dd9cd7
Don't enforce a minimum width
Jan 20, 2026
15d3da0
Fix dictionaries/spellings suggestions thanks to ecm-pushbx patches i…
Jan 21, 2026
952feaf
Github release
Jan 22, 2026
fcb3901
include my initials, don't want to create version confusion if ever K…
Jan 22, 2026
be3ebe6
Klaus' full name. Typo fixes.
Jan 22, 2026
f9b6e15
Don't check in keystore.jks
Jan 22, 2026
6db79a6
Workflow for creating release
Jan 22, 2026
3b9d869
Signing config
Jan 22, 2026
00b16e7
Ënnerstëtzung fir Lëtzebuergeschen Dictionnaire (muss awer extra vun…
Jan 23, 2026
5dd767a
preparing new release
Jan 23, 2026
1e0888f
Switch to JDK 21
Jan 24, 2026
1a7deca
Workaround for width of small popup on multi-character key
Jan 25, 2026
1f00d76
Mark PrefScreenView as exported to fix crash
BellCubeDev Feb 27, 2026
0865338
Mark other sub-screens as exported too
BellCubeDev Feb 28, 2026
5bc4da1
Merge pull request #1 from BellCubeDev/master
AlainKnaff Feb 28, 2026
4841354
New version 1.42.3 to fix navigating to sub setting screens
Feb 28, 2026
4689465
When focusing another input field, forget partial completions accumul…
Mar 5, 2026
6d84064
Put v back, do we need it for GitHub actions
Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions .github/ISSUE_TEMPLATE/bug_report.md

This file was deleted.

64 changes: 64 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
on:
push:
branches: master
tags: '*'

jobs:
release_build:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')

steps:
- uses: actions/checkout@v2.6.0

- name: Setup JAVA 21
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: 21

- name: Cache Gradle and wrapper
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}

#1
- name: Decode Keystore
env:
# Encode using base64 app/keystore.jks | tr -d '\012'; echo
ENCODED_STRING: ${{ secrets.SIGNING_KEY_STORE_BASE64 }}
SIGNING_KEY_STORE_PATH: keystore.jks

run: |
echo "$ENCODED_STRING" > keystore-b64.txt
base64 -d keystore-b64.txt > app/$SIGNING_KEY_STORE_PATH

#2
- name: Build Release apk
env:
SIGNING_KEY_STORE_PATH: keystore.jks
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
run: ./gradlew assembleRelease

#3
- name: Rename apk
run: |
mv -v app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/`basename ${GITHUB_REPOSITORY}`_${GITHUB_REF_NAME}.apk
#4
- name: Upload Release Build to Artifacts
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: app/build/outputs/apk/release/
#5
- name: Create Github Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
files: |
app/build/outputs/apk/release/*_*.apk
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@
.DS_Store
/build
/captures
gradle
.externalNativeBuild
/app/.cxx
.env
.gitignore
README.html
keystore.jks
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## Status of this fork ##

This is a fork of the original hacker's keyboard by Klaus Weidner. The original had fallen behind on evolution Android evolution, and was not even compilable any more in today's environments. I took it upon myself to bring it up to Sdk 36 level (Android 16), and got dictionaries working again.

[Releases here](../../releases)

## Dictionaries ##

Hacker's keyboard uses Anysoft keyboard's dictionaries (compatible APIs), which you find easily on F-Droid, *except* the English dictionary. Probably because English in built into Anysoft keyboard, and thus it doesn't need any external dictionary for it. Fortunately, you can still find an older version at [Apkpure](https://apkpure.com/english-for-anysoftkeyboard/com.anysoftkeyboard.languagepack.mirfatif.english).


# Original README.md #

## Overview ##

**WARNING:** *This is a rather ancient project that was originally developed back in 2011 based on the Android 2.3 (Gingerbread) AOSP keyboard. While it still works as-is for many users, it would need some major rewrites to work with newer APIs, and some features such as language switching or popup keys don't work right on modern Android systems. I'm not currently planning on significant updates, and it's possible that it will stop working on modern devices or will no longer be updateable via the Google Play store due to minimum API level requirements. Play Store requires targeting API level 29 (Android 10), while the code was written for API level 9 (Android 2.3) from 2011.*
Expand Down
35 changes: 23 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 26
compileSdkVersion 36
namespace = 'org.pocketworkstation.pckeyboard'
defaultConfig {
applicationId 'org.pocketworkstation.pckeyboard'
minSdkVersion 14
targetSdkVersion 26
versionCode 1041001
versionName "v1.41.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
applicationId = 'org.pocketworkstation.pckeyboard'
minSdkVersion = 21
targetSdkVersion = 36
versionCode = 1042004
versionName = "v1.42.4ak"
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}

signingConfigs {
release {
storeFile = file("keystore.jks")
storePassword = System.getenv("SIGNING_STORE_PASSWORD")
keyAlias = System.getenv("SIGNING_KEY_ALIAS")
keyPassword = System.getenv("SIGNING_KEY_PASSWORD")
}
}

buildTypes {
release {
minifyEnabled false
minifyEnabled = false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig = signingConfigs.release
}
}
externalNativeBuild {
Expand All @@ -38,9 +50,8 @@ android {

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation "com.android.support:support-compat:26.0.0"
testImplementation 'junit:junit:4.12'
implementation 'androidx.appcompat:appcompat:1.6.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
}
11 changes: 11 additions & 0 deletions app/lint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="ExtraTranslation" severity="ignore" />
<!-- not pretty, but no reason why this should be blocking
-->

<issue id="NotificationPermission" severity="ignore" />
<!-- ignore this for now, obscure feature which most won't use,
and if they do they'll grant the permission pro-actively -->

</lint>
36 changes: 26 additions & 10 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.pocketworkstation.pckeyboard">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.faketouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

<queries>
<intent>
<action android:name="com.menny.android.anysoftkeyboard.KEYBOARD" />
</intent>
<intent>
<action android:name="org.pocketworkstation.DICT" />
</intent>
</queries>

<application android:label="@string/english_ime_name"
android:allowBackup="true"
android:backupAgent="LatinIMEBackupAgent"
Expand All @@ -18,21 +27,24 @@

<service android:name="LatinIME"
android:label="@string/english_ime_name"
android:permission="android.permission.BIND_INPUT_METHOD">
android:permission="android.permission.BIND_INPUT_METHOD"
android:exported="false">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>

<activity android:name="Main" android:label="Hacker's Keyboard">
<activity android:name="Main" android:label="Hacker's Keyboard"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<activity android:name="LatinIMESettings" android:label="@string/english_ime_settings">
<activity android:name="LatinIMESettings" android:label="@string/english_ime_settings"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.pocketworkstation.pckeyboard.SETTINGS"/>
Expand All @@ -41,7 +53,8 @@
</activity>

<activity android:name="InputLanguageSelection"
android:label="@string/language_selection_title">
android:label="@string/language_selection_title"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.pocketworkstation.pckeyboard.INPUT_LANGUAGE_SELECTION"/>
Expand All @@ -50,16 +63,18 @@
</activity>

<activity android:name="PrefScreenActions"
android:label="@string/pref_screen_actions_title">
android:label="@string/pref_screen_actions_title"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.pocketworkstation.pckeyboard.PREFS_ACTIONS"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

<activity android:name="PrefScreenView"
android:label="@string/pref_screen_actions_title">
android:label="@string/pref_screen_actions_title"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.pocketworkstation.pckeyboard.PREFS_VIEW"/>
Expand All @@ -68,7 +83,8 @@
</activity>

<activity android:name="PrefScreenFeedback"
android:label="@string/pref_screen_feedback_title">
android:label="@string/pref_screen_feedback_title"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.pocketworkstation.pckeyboard.PREFS_FEEDBACK"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public void addWord(String word, int addFrequency) {

synchronized (mPendingWritesLock) {
// Write a null frequency if it is to be deleted from the db
mPendingWrites.put(word, freq == 0 ? null : new Integer(freq));
mPendingWrites.put(word, freq == 0 ? null : Integer.valueOf(freq));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import android.util.Log;

public class AutoSummaryListPreference extends ListPreference {
private static final String TAG = "HK/AutoSummaryListPreference";
private static final String TAG = "HK/AutoSummaryListPrf";

public AutoSummaryListPreference(Context context) {
super(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,11 @@ public int computeHorizontalScrollRange() {
*/
@Override
protected void onDraw(Canvas canvas) {
if (canvas != null) {
super.onDraw(canvas);
}
super.onDraw(canvas);
_onDraw(canvas);
}

private void _onDraw(Canvas canvas) {
mTotalWidth = 0;

final int height = getHeight();
Expand Down Expand Up @@ -335,7 +337,7 @@ public void setSuggestions(List<CharSequence> suggestions, boolean completions,
mTargetScrollX = 0;
mHaveMinimalSuggestion = haveMinimalSuggestion;
// Compute the total width
onDraw(null);
_onDraw(null);
invalidate();
requestLayout();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ public static String getSpacing(char nonSpacing) {

private static String doNormalise(String input)
{
if (Build.VERSION.SDK_INT >= 9) {
return Normalizer.normalize(input, Normalizer.Form.NFC);
}
return input;
return Normalizer.normalize(input, Normalizer.Form.NFC);
}

public static String normalize(String input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,23 @@ public class InputLanguageSelection extends PreferenceActivity {
"ar", "bg", "bg_ST", "ca", "cs", "cs_QY", "da", "de", "de_NE",
"el", "en", "en_CX", "en_DV", "en_GB", "es", "es_LA", "es_US",
"fa", "fi", "fr", "fr_CA", "he", "hr", "hu", "hu_QY", "hy", "in",
"it", "iw", "ja", "ka", "ko", "lo", "lt", "lv", "nb", "nl", "pl",
"it", "iw", "ja", "ka", "ko", "lb", "lb_LU", "lo", "lt", "lv", "nb", "nl", "pl",
"pt", "pt_PT", "rm", "ro", "ru", "ru_PH", "si", "sk", "sk_QY", "sl",
"sr", "sv", "ta", "th", "tl", "tr", "uk", "vi", "zh_CN", "zh_TW"
};

private static final String[] KBD_5_ROW = {
"ar", "bg", "bg_ST", "cs", "cs_QY", "da", "de", "de_NE", "el",
"en", "en_CX", "en_DV", "en_GB", "es", "es_LA", "fa", "fi", "fr",
"fr_CA", "he", "hr", "hu", "hu_QY", "hy", "it", "iw", "lo", "lt",
"fr_CA", "he", "hr", "hu", "hu_QY", "hy", "it", "iw", "lb", "lo", "lt",
"nb", "pt_PT", "ro", "ru", "ru_PH", "si", "sk", "sk_QY", "sl",
"sr", "sv", "ta", "th", "tr", "uk"
};

private static final String[] KBD_4_ROW = {
"ar", "bg", "bg_ST", "cs", "cs_QY", "da", "de", "de_NE", "el",
"en", "en_CX", "en_DV", "es", "es_LA", "es_US", "fa", "fr", "fr_CA",
"he", "hr", "hu", "hu_QY", "iw", "nb", "ru", "ru_PH", "sk", "sk_QY",
"he", "hr", "hu", "hu_QY", "iw", "lb", "lb_LU", "nb", "ru", "ru_PH", "sk", "sk_QY",
"sl", "sr", "sv", "tr", "uk"
};

Expand Down Expand Up @@ -118,6 +118,8 @@ private static String getLocaleName(Locale l) {
} else {
return "български език (Phonetic)";
}
} else if (lang.equals("lb")) {
return "Lëtzebuergesch";
} else {
return LanguageSwitcher.toTitleCase(l.getDisplayName(l));
}
Expand Down
Loading