Skip to content

Commit 53a78c6

Browse files
authored
Merge pull request #119 from gazlaws-dev/59473230/update-android-version
Update android version, add fix for 31 notification
2 parents 44da283 + 8a64bef commit 53a78c6

File tree

16 files changed

+362
-209
lines changed

16 files changed

+362
-209
lines changed

.github/workflows/android.yml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
name: Codeboard Android CI
2-
1+
name: Codeboard Android CI New
32
on: [push]
43

54
jobs:
65
build:
76

8-
runs-on: ubuntu-latest
7+
runs-on: windows-latest
98

109
steps:
11-
- uses: actions/checkout@v1
12-
- name: set up JDK 1.8
13-
uses: actions/setup-java@v1
14-
with:
15-
java-version: 1.8
16-
- name: Set Gradle permissions
17-
run: chmod a+x ./gradlew
18-
- name: Build with Gradle
19-
run: ./gradlew build
10+
- uses: actions/checkout@v1
11+
- name: Build with Gradle
12+
run: |
13+
$env:JAVA_HOME = "$env:JAVA_HOME_17_X64"
14+
./gradlew assemble
15+
dir .
16+
- uses: actions/upload-artifact@v4
17+
with:
18+
name: apk
19+
path: app/build/outputs
20+
retention-days: 1

.idea/compiler.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/deploymentTargetDropDown.xml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/migrations.xml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations.xml

Lines changed: 0 additions & 12 deletions
This file was deleted.

app/build.gradle

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdkVersion 30
5-
buildToolsVersion '30.0.3'
4+
namespace "com.gazlaws.codeboard"
5+
compileSdkVersion 34
6+
buildToolsVersion '34.0.0'
67

78
defaultConfig {
89
applicationId "com.gazlaws.codeboard"
910
minSdkVersion 23
10-
targetSdkVersion 30
11-
versionCode 20
12-
versionName "6.0.0"
11+
targetSdkVersion 34
12+
versionCode 21
13+
versionName "6.0.1"
1314
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1415
}
1516
buildTypes {
@@ -41,32 +42,32 @@ repositories {
4142

4243
dependencies {
4344

44-
api 'androidx.appcompat:appcompat:1.2.0'
45+
api 'androidx.appcompat:appcompat:1.6.1'
4546
api 'androidx.legacy:legacy-support-v13:1.0.0'
46-
api 'androidx.preference:preference:1.1.1'
47+
api 'androidx.preference:preference:1.2.1'
4748

48-
implementation 'com.google.android.material:material:1.4.0-alpha02'
49+
implementation 'com.google.android.material:material:1.11.0'
4950

5051
//https://github.com/AppIntro/AppIntro
51-
implementation 'com.github.AppIntro:AppIntro:6.1.0'
52+
implementation 'com.github.AppIntro:AppIntro:6.3.1'
5253

5354
//Colour picker
5455
implementation 'com.pes.materialcolorpicker:library:1.2.5'
5556

5657
// Required for local unit tests (JUnit 4 framework)
57-
testImplementation 'junit:junit:4.12'
58+
testImplementation 'junit:junit:4.13.2'
5859

5960
// Required for instrumented tests
60-
implementation 'androidx.annotation:annotation:1.2.0'
61-
androidTestImplementation 'androidx.annotation:annotation:1.2.0'
61+
implementation 'androidx.annotation:annotation:1.7.1'
62+
androidTestImplementation 'androidx.annotation:annotation:1.7.1'
6263

6364

6465
// Core library
65-
androidTestImplementation 'androidx.test:core:1.3.0'
66+
androidTestImplementation 'androidx.test:core:1.5.0'
6667

6768
// AndroidJUnitRunner and JUnit Rules
68-
androidTestImplementation 'androidx.test:runner:1.3.0'
69+
androidTestImplementation 'androidx.test:runner:1.5.2'
6970

70-
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
71+
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
7172

7273
}

app/src/main/AndroidManifest.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="com.gazlaws.codeboard"
33
>
4+
45
<uses-permission android:name="android.permission.VIBRATE"/>
6+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
57

68
<application
79
android:allowBackup="true"
@@ -14,7 +16,8 @@
1416
<service
1517
android:name=".CodeBoardIME"
1618
android:label="@string/codeboard_ime"
17-
android:permission="android.permission.BIND_INPUT_METHOD">
19+
android:permission="android.permission.BIND_INPUT_METHOD"
20+
android:exported="true">
1821
<meta-data
1922
android:name="android.view.im"
2023
android:resource="@xml/method" />
@@ -27,7 +30,7 @@
2730
<activity android:name="com.gazlaws.codeboard.MainActivity"
2831
android:label="@string/app_name"
2932
android:launchMode="singleTask"
30-
>
33+
android:exported="true">
3134
<intent-filter>
3235
<action android:name="android.intent.action.MAIN" />
3336
<category android:name="android.intent.category.LAUNCHER" />

app/src/main/java/com/gazlaws/codeboard/CodeBoardIME.java

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.gazlaws.codeboard;
22

3+
import android.Manifest;
4+
import android.annotation.SuppressLint;
35
import android.app.NotificationChannel;
46
import android.app.NotificationManager;
57
import android.app.PendingIntent;
@@ -8,6 +10,7 @@
810
import android.content.Context;
911
import android.content.Intent;
1012
import android.content.IntentFilter;
13+
import android.content.pm.PackageManager;
1114
import android.content.res.Configuration;
1215
import android.graphics.Color;
1316
import android.inputmethodservice.InputMethodService;
@@ -16,6 +19,7 @@
1619
import android.os.Handler;
1720
import android.os.IBinder;
1821
import android.os.Looper;
22+
import android.os.ResultReceiver;
1923
import android.os.Vibrator;
2024
import android.util.Log;
2125
import android.view.KeyEvent;
@@ -26,8 +30,10 @@
2630
import android.view.inputmethod.InputMethodManager;
2731
import android.media.MediaPlayer; // for keypress sound
2832

33+
import androidx.core.app.ActivityCompat;
2934
import androidx.core.app.NotificationCompat;
3035
import androidx.core.app.NotificationManagerCompat;
36+
import androidx.core.app.RemoteInput;
3137
import androidx.core.graphics.ColorUtils;
3238

3339
import com.gazlaws.codeboard.layout.Box;
@@ -46,6 +52,8 @@
4652
import java.util.TimerTask;
4753

4854
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
55+
import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
56+
import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS;
4957

5058
/*Created by Ruby(aka gazlaws) on 13/02/2016.
5159
*/
@@ -73,7 +81,7 @@ public void onKey(int primaryCode, int[] KeyCodes) {
7381
//NOTE: Long press goes second, this is onDown
7482
InputConnection ic = getCurrentInputConnection();
7583
char code = (char) primaryCode;
76-
Log.i(getClass().getSimpleName(), "onKey: " + primaryCode);
84+
Log.d(getClass().getSimpleName(), "onKey: " + primaryCode);
7785

7886
switch (primaryCode) {
7987
//First handle cases that don't use shift/ctrl meta modifiers
@@ -274,7 +282,7 @@ public void onKey(int primaryCode, int[] KeyCodes) {
274282
}
275283
if (ke != 0) {
276284

277-
Log.i(getClass().getSimpleName(), "onKey: keyEvent " + ke);
285+
Log.d(getClass().getSimpleName(), "onKey: keyEvent " + ke);
278286

279287
/*
280288
* The if statement was added in order to prevent the space button
@@ -284,7 +292,9 @@ public void onKey(int primaryCode, int[] KeyCodes) {
284292
* and afterwards produce the right output to the screen.
285293
* TODO: Investigate whether KeyEvent.ACTION_UP is still required.
286294
*/
287-
if (primaryCode != 32) { ic.sendKeyEvent (new KeyEvent (0, 0, KeyEvent.ACTION_DOWN, ke, 0, meta)); }
295+
if (primaryCode != 32) {
296+
ic.sendKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, ke, 0, meta));
297+
}
288298

289299
ic.sendKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP, ke, 0, meta));
290300
} else {
@@ -341,6 +351,19 @@ public void run() {
341351
}, ViewConfiguration.getLongPressTimeout());
342352
}
343353

354+
@Override
355+
public void onExtractingInputChanged(EditorInfo ei){
356+
Log.d(getClass().getSimpleName(), "onExtractingInputChanged: ");
357+
}
358+
@Override
359+
public void requestHideSelf(int flags){
360+
int new_flag = HIDE_IMPLICIT_ONLY;
361+
new_flag = flags;
362+
Log.d(getClass().getSimpleName(), "requestHideSelf: "+new_flag + ","+ flags);
363+
// do nothing
364+
super.requestHideSelf(new_flag);
365+
}
366+
344367
@Override
345368
public void onWindowHidden() {
346369
super.onWindowHidden();
@@ -361,10 +384,10 @@ public void onRelease(int primaryCode) {
361384
* If it was, we don't do anything,
362385
* but If it wasn't, we print a "space" to the screen.
363386
*/
364-
if ((primaryCode == 32) && (! longPressedSpaceButton)) {
387+
if ((primaryCode == 32) && (!longPressedSpaceButton)) {
365388

366-
InputConnection ic = getCurrentInputConnection ();
367-
ic.commitText (String.valueOf ((char) primaryCode), 1);
389+
InputConnection ic = getCurrentInputConnection();
390+
ic.commitText(String.valueOf((char) primaryCode), 1);
368391
}
369392

370393
longPressedSpaceButton = false;
@@ -671,6 +694,7 @@ private void createNotificationChannel() {
671694
private static final int NOTIFICATION_ONGOING_ID = 1001;
672695

673696
//Code from Hacker keyboard's source
697+
@SuppressLint("MissingPermission")
674698
private void setNotification(boolean visible) {
675699
NotificationManager mNotificationManager =
676700
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -682,19 +706,55 @@ private void setNotification(boolean visible) {
682706
createNotificationChannel();
683707
mNotificationReceiver = new NotificationReceiver(this);
684708
final IntentFilter pFilter = new IntentFilter(NotificationReceiver.ACTION_SHOW);
685-
pFilter.addAction(NotificationReceiver.ACTION_SETTINGS);
686-
registerReceiver(mNotificationReceiver, pFilter);
687709

688-
Intent notificationIntent = new Intent(NotificationReceiver.ACTION_SHOW);
689-
PendingIntent contentIntent =
690-
PendingIntent.getBroadcast(getApplicationContext(), 1, notificationIntent, 0);
710+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
711+
registerReceiver(mNotificationReceiver, pFilter, Context.RECEIVER_NOT_EXPORTED);
712+
} else {
713+
registerReceiver(mNotificationReceiver, pFilter);
714+
}
715+
716+
717+
Intent imeIntent = new Intent(NotificationReceiver.ACTION_SHOW);
718+
PendingIntent imePendingIntent =
719+
PendingIntent.getBroadcast(getApplicationContext(),
720+
1, imeIntent, PendingIntent.FLAG_IMMUTABLE);
691721

692-
Intent configIntent = new Intent(NotificationReceiver.ACTION_SETTINGS);
693-
PendingIntent configPendingIntent =
694-
PendingIntent.getBroadcast(getApplicationContext(), 2, configIntent, 0);
722+
// BUG: IM closes when notification drawer is closed
723+
// try making a input field here?
724+
// Key for the string that's delivered in the action's intent.
725+
String KEY_TEXT_REPLY = "key_text_reply";
695726

727+
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
728+
.setLabel("Now click first icon")
729+
.build();
730+
731+
732+
// Build a PendingIntent for the keyboard action to trigger first
733+
int flags = PendingIntent.FLAG_MUTABLE;
734+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
735+
flags = PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT;
736+
}
737+
PendingIntent replyPendingIntent =
738+
PendingIntent.getBroadcast(getApplicationContext(),
739+
2,
740+
imeIntent,
741+
flags);
742+
743+
744+
// Create the reply action and add the remote input.
745+
NotificationCompat.Action action =
746+
new NotificationCompat.Action.Builder(R.drawable.icon_large,
747+
getString(R.string.notification_action_open_keyboard_workaround), replyPendingIntent)
748+
.addRemoteInput(remoteInput)
749+
.build();
750+
751+
Intent settingsIntent = new Intent(this, MainActivity.class);
752+
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
753+
PendingIntent settingsPendingIntent =
754+
PendingIntent.getActivity(this,0
755+
, settingsIntent, PendingIntent.FLAG_IMMUTABLE);
696756
String title = "Show Codeboard Keyboard";
697-
String body = "Select this to open the keyboard. Disable in settings.";
757+
String body = "Select this to open the keyboard. Disable in settings. You may have to fix open the fix as a workaround for newer Android versions";
698758

699759
NotificationCompat.Builder mBuilder =
700760
new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
@@ -704,17 +764,17 @@ private void setNotification(boolean visible) {
704764
.setTicker(text)
705765
.setContentTitle(title)
706766
.setContentText(body)
707-
.setContentIntent(contentIntent)
767+
.setContentIntent(imePendingIntent)
708768
.setOngoing(true)
709769
.addAction(R.drawable.icon_large, getString(R.string.notification_action_open_keyboard),
710-
contentIntent)
770+
imePendingIntent)
711771
.addAction(R.drawable.icon_large, getString(R.string.notification_action_settings),
712-
configPendingIntent)
772+
settingsPendingIntent)
773+
.addAction(action)
713774
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
714775

715776
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
716777

717-
// notificationId is a unique int for each notification that you must define
718778
notificationManager.notify(NOTIFICATION_ONGOING_ID, mBuilder.build());
719779

720780
} else if (!visible && mNotificationReceiver != null) {

0 commit comments

Comments
 (0)