abouttreesummaryrefslogcommitdiff
path: root/CONTRIBUTING.md
blob: 9af5fa1b45b647e27345d2d63c77dc61a65a9209 (preview) (code) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# Contributing

Thanks for contributing :)

## Building the app

The application uses Gradle and can be used with Android Studio, but using
Android Studio is not required. The build dependencies are:
- OpenJDK 17
- Android SDK: build tools (minimum `28.0.1`), platform `30`

Python 3 is required to update generated files but not to build the app.

For Android Studio users, no more setup is needed.

For Nix users, the right environment can be obtained with `nix-shell ./shell.nix`.
Instructions to install Nix are [here](https://nixos.wiki/wiki/Nix_Installation_Guide).

If you don't use Android Studio or Nix, you have to inform Gradle about the
location of your Android SDK by either:
- Setting the `ANDROID_HOME` environment variable to point to the android sdk or
- Creating the file `local.properties` and writing
  `sdk.dir=<location_of_android_home>` into it.

Building the debug apk:

```sh
./gradlew assembleDebug
```

If the build succeeds, the debug apk is located in `build/outputs/apk/debug/app-debug.apk`.

## Debugging on your phone

First [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb#Enabling).
Then connect your phone to your computer using an USB cable or via wireless
debugging.

If you use Android Studio, this process will be automatic and you don't have to
follow this guide anymore.

And finally, install the application with:
```sh
./gradlew installDebug
```

The released version of the application won't be removed, both versions will
be installed at the same time.

## Debugging the application: INSTALL_FAILED_UPDATE_INCOMPATIBLE

`./gradlew installDebug` can fail with the following error message:

```
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':installDebug'.
> java.util.concurrent.ExecutionException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package juloo.keyboard2.debug signatures do not match newer version; ignoring!
```

The application can't be "updated" because the temporary certificate has been
lost. The solution is to uninstall and install again.
The application must be enabled again in the settings.

```sh
adb uninstall juloo.keyboard2.debug
./gradlew installDebug
```

## Specifying a debug signing certificate on Github Actions

It's possible to specify the signing certificate that the automated build
should use.
After you successfully run `./gradlew asssembleDebug`, (thus a debug.keystore
exists) you can use this second command to generate a base64 stringified
version of it:

```sh
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
```

This will create the file `debug.keystore.asc`, paste its content into a new
Github secret named `DEBUG_KEYSTORE`.

## Guidelines

### Adding a layout

Layouts are defined in XML, see `res/xml/latn_qwerty_us.xml`.
An online tool for editing layout files written by @Lixquid is available
[here](https://unexpected-keyboard-layout-editor.lixquid.com/).

Makes sure to specify the `name` attribute like in `latn_qwerty_us.xml`,
otherwise the layout won't be added to the app.

The layout file must be placed in the `res/xml/` directory and named according to:
- script (`latn` for latin, etc..)
- layout name (eg. the name of a standard)
- country code (or language code if more adequate)

Then, run `./gradlew genLayoutsList` to add the layout to the app.

The last step will update the file `res/values/layouts.xml`, that you should
not edit directly.

Run `./gradlew checkKeyboardLayouts` to check some properties about your
layout. This will change the file `check_layout.output`, which you should
commit.

#### Adding a programming layout

A programming layout must contain all ASCII characters.
The current programming layouts are: QWERTY, Dvorak and Colemak.

See for example, Dvorak, added in https://github.com/Julow/Unexpected-Keyboard/pull/16

It's best to leave free spots on the layout for language-specific symbols that
are added automatically when necessary.
These symbols are defined in `res/xml/method.xml` (`extra_keys`).

It's possible to place extra keys with the `loc` prefix. These keys are
normally hidden unless they are needed.

Some users cannot easily type the characters close the the edges of the screen
due to a bulky phone case. It is best to avoid placing important characters
there (such as the digits or punctuation).

#### Adding a localized layout

Localized layouts (a layout specific to a language) are gladly accepted.
See for example: 4333575 (Bulgarian), 88e2175 (Latvian), 133b6ec (German).

They don't need to contain every ASCII characters (although it's useful in
passwords) and dead-keys.

### Adding support for a language

Supported locales are defined in `res/xml/method.xml`.

The attributes `languageTag` and `imeSubtypeLocale` define a locale, the
attribute `imeSubtypeExtraValue` defines the default layout and the dead-keys
and other extra keys to show.

The list of language tags (generally two letters)
and locales (generally of the form `xx_XX`)
can be found in this [stackoverflow answer](https://stackoverflow.com/a/7989085)

### Updating translations

The text used in the app is written in `res/values-<language_tag>/strings.xml`.

The list of language tags can be found in this
[stackoverflow answer](https://stackoverflow.com/a/7989085)

The first part before the `_` is used, for example,
`res/values-fr/strings.xml` for French,
`res/values-lv/strings.xml` for Latvian.

Commented-out lines indicate missing translations:

```xml
  <!-- <string name="pref_layouts_add">Add an alternate layout</string> -->
```

Remove the `<!--` and `-->` parts and change the text.

### Adding a translation

The `res/values-<language_tag>/strings.xml` file must be created by copying the
default translation in `res/values/strings.xml`, which contain the structure of
the file and the English strings.

To check that `strings.xml` is formatted correctly, run
`./gradlew syncTranslations`. This will modify your files.

The store description is found in `metadata/android/<locale>/`,
`short_description.txt` and `full_description.txt`.
The short description must not exceed 80 characters.
Translating changelogs is not useful.

The app name might be partially translated, the "Unexpected" word should remain
untranslated.

As translations need to be updated regularly, you can subscribe to this issue
to receive a notification when an update is needed:
https://github.com/Julow/Unexpected-Keyboard/issues/373

### Adding key combinations

Key combinations are defined in `srcs/juloo.keyboard2/KeyModifier.java`.
For example, keys modified by the `Fn` key are defined in method
`apply_fn_char`.

Keys with special meaning are defined in `KeyValue.java` in method
`getKeyByName`. Their special action are defined in `KeyEventHandler.java` in
method `key_up`

Contributing

Thanks for contributing :)

Building the app

The application uses Gradle and can be used with Android Studio, but using Android Studio is not required. The build dependencies are:

  • OpenJDK 17
  • Android SDK: build tools (minimum 28.0.1), platform 30

Python 3 is required to update generated files but not to build the app.

For Android Studio users, no more setup is needed.

For Nix users, the right environment can be obtained with nix-shell ./shell.nix. Instructions to install Nix are here.

If you don't use Android Studio or Nix, you have to inform Gradle about the location of your Android SDK by either:

  • Setting the ANDROID_HOME environment variable to point to the android sdk or
  • Creating the file local.properties and writing sdk.dir=<location_of_android_home> into it.

Building the debug apk:

./gradlew assembleDebug

If the build succeeds, the debug apk is located in build/outputs/apk/debug/app-debug.apk.

Debugging on your phone

First Enable adb debugging on your device. Then connect your phone to your computer using an USB cable or via wireless debugging.

If you use Android Studio, this process will be automatic and you don't have to follow this guide anymore.

And finally, install the application with:

./gradlew installDebug

The released version of the application won't be removed, both versions will be installed at the same time.

Debugging the application: INSTALL_FAILED_UPDATE_INCOMPATIBLE

./gradlew installDebug can fail with the following error message:

FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':installDebug'.
> java.util.concurrent.ExecutionException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package juloo.keyboard2.debug signatures do not match newer version; ignoring!

The application can't be "updated" because the temporary certificate has been lost. The solution is to uninstall and install again. The application must be enabled again in the settings.

adb uninstall juloo.keyboard2.debug
./gradlew installDebug

Specifying a debug signing certificate on Github Actions

It's possible to specify the signing certificate that the automated build should use. After you successfully run ./gradlew asssembleDebug, (thus a debug.keystore exists) you can use this second command to generate a base64 stringified version of it:

gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"

This will create the file debug.keystore.asc, paste its content into a new Github secret named DEBUG_KEYSTORE.

Guidelines

Adding a layout

Layouts are defined in XML, see res/xml/latn_qwerty_us.xml. An online tool for editing layout files written by @Lixquid is available here.

Makes sure to specify the name attribute like in latn_qwerty_us.xml, otherwise the layout won't be added to the app.

The layout file must be placed in the res/xml/ directory and named according to:

  • script (latn for latin, etc..)
  • layout name (eg. the name of a standard)
  • country code (or language code if more adequate)

Then, run ./gradlew genLayoutsList to add the layout to the app.

The last step will update the file res/values/layouts.xml, that you should not edit directly.

Run ./gradlew checkKeyboardLayouts to check some properties about your layout. This will change the file check_layout.output, which you should commit.

Adding a programming layout

A programming layout must contain all ASCII characters. The current programming layouts are: QWERTY, Dvorak and Colemak.

See for example, Dvorak, added in https://github.com/Julow/Unexpected-Keyboard/pull/16

It's best to leave free spots on the layout for language-specific symbols that are added automatically when necessary. These symbols are defined in res/xml/method.xml (extra_keys).

It's possible to place extra keys with the loc prefix. These keys are normally hidden unless they are needed.

Some users cannot easily type the characters close the the edges of the screen due to a bulky phone case. It is best to avoid placing important characters there (such as the digits or punctuation).

Adding a localized layout

Localized layouts (a layout specific to a language) are gladly accepted. See for example: 4333575 (Bulgarian), 88e2175 (Latvian), 133b6ec (German).

They don't need to contain every ASCII characters (although it's useful in passwords) and dead-keys.

Adding support for a language

Supported locales are defined in res/xml/method.xml.

The attributes languageTag and imeSubtypeLocale define a locale, the attribute imeSubtypeExtraValue defines the default layout and the dead-keys and other extra keys to show.

The list of language tags (generally two letters) and locales (generally of the form xx_XX) can be found in this stackoverflow answer

Updating translations

The text used in the app is written in res/values-<language_tag>/strings.xml.

The list of language tags can be found in this stackoverflow answer

The first part before the _ is used, for example, res/values-fr/strings.xml for French, res/values-lv/strings.xml for Latvian.

Commented-out lines indicate missing translations:

  <!-- <string name="pref_layouts_add">Add an alternate layout</string> -->

Remove the <!-- and --> parts and change the text.

Adding a translation

The res/values-<language_tag>/strings.xml file must be created by copying the default translation in res/values/strings.xml, which contain the structure of the file and the English strings.

To check that strings.xml is formatted correctly, run ./gradlew syncTranslations. This will modify your files.

The store description is found in metadata/android/<locale>/, short_description.txt and full_description.txt. The short description must not exceed 80 characters. Translating changelogs is not useful.

The app name might be partially translated, the "Unexpected" word should remain untranslated.

As translations need to be updated regularly, you can subscribe to this issue to receive a notification when an update is needed: https://github.com/Julow/Unexpected-Keyboard/issues/373

Adding key combinations

Key combinations are defined in srcs/juloo.keyboard2/KeyModifier.java. For example, keys modified by the Fn key are defined in method apply_fn_char.

Keys with special meaning are defined in KeyValue.java in method getKeyByName. Their special action are defined in KeyEventHandler.java in method key_up