Skip to content

ANDROID: new module androidforeground (replace #256) #404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 39 additions & 0 deletions modules/androidforeground/ANDROID_c_additions
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* androidforeground -*-C-*- */

int android_start_ln_foreground_service()
{
JNIEnv *env = GetJNIEnv();
if (env&&globalObj){
jclass main_class = (*env)->FindClass(env, "@SYS_PACKAGE_SLASH@/@SYS_APPNAME@");
jmethodID method = main_class ? (*env)->GetMethodID(env, main_class, "startLnForegroundService", "()V") : NULL;
if(main_class) (*env)->DeleteLocalRef(env, main_class);
if(!method) {
JNI_forward_exception_to_gambit(env);
return -1;
}
(*env)->CallVoidMethod(env, globalObj, method);
(*env)->DeleteLocalRef(env, method);
if(JNI_forward_exception_to_gambit(env)) { return -2; }
return 0;
}
}

int android_stop_ln_foreground_service()
{
JNIEnv *env = GetJNIEnv();
if (env&&globalObj){
jclass main_class = (*env)->FindClass(env, "@SYS_PACKAGE_SLASH@/@SYS_APPNAME@");
jmethodID method = main_class ? (*env)->GetMethodID(env, main_class, "stopLnForegroundService", "()V") : NULL;
if(main_class) (*env)->DeleteLocalRef(env, main_class);
if(!method) {
JNI_forward_exception_to_gambit(env);
return -1;
}
(*env)->CallVoidMethod(env, globalObj, method);
(*env)->DeleteLocalRef(env, method);
if(JNI_forward_exception_to_gambit(env)) { return -2; }
return 0;
}
}

/* EOF androidforeground */
34 changes: 34 additions & 0 deletions modules/androidforeground/ANDROID_java_activityadditions
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* androidforeground -*- mode: java; c-basic-offset: 2; -*- */

void startLnForegroundService() {
/* API 26+: In order to compile for prior API versions comment out
* the following attempt to disable battery optimizations
*/
@IF_ANDROIDAPI_GT_22@
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1) {
String pkg=getPackageName();
PowerManager pm=getSystemService(PowerManager.class);
if(!pm.isIgnoringBatteryOptimizations(pkg)) {
// See also the comment in ANDROID_xml_permissions: Google may
// not like the required
// ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS permission
// being used.
//
// If it is not requested in the permissions file,
// uncomment the following startActivityForResult(...) and
// comment out startActivity(...) in the line after.

// startActivityForResult(new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS), 0);
startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).setData(Uri.parse("package:"+pkg)));
}
}
// end of IF_ANDROIDAPI_GT_22 */

startService(new Intent(this, LambdaNativeForegroundService.class));
}

void stopLnForegroundService() {
stopService(new Intent(this, LambdaNativeForegroundService.class));
}

/* EOF androidforeground */
2 changes: 2 additions & 0 deletions modules/androidforeground/ANDROID_java_imports
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import android.provider.Settings;
import android.os.Build;
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* -*- mode: java; c-basic-offset: 2; -*- */

package @SYS_PACKAGE_DOT@;
@IF_ANDROIDAPI_GT_25@
import android.app.NotificationChannel;
import android.app.NotificationManager;
/* end of IF_ANDROIDAPI_GT_25 */

import android.util.Log;
import android.app.Service;
import android.app.Notification;
import android.app.Notification.Builder;

//import android.support.v4.app.NotificationCompat;

import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;

public class LambdaNativeForegroundService extends Service {
final static int notificationIsRunningId = 1;
boolean running=true;
Thread backgroundThread;
public LambdaNativeForegroundService() {
}
private Notification.Builder make_notification_template() {
return new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
// .setContentText("TBD")
.setSmallIcon(R.drawable.icon)
// .setLargeIcon(aBitmap)
.setOngoing(true);
}
private void keepAwake_LT_API26() {
startForeground(notificationIsRunningId, make_notification_template().build());
}
private void keepAwake() {
@IF_ANDROIDAPI_GT_25@
if(true) {
NotificationManager mgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert mgr != null;
NotificationChannel channel =
new NotificationChannel ("@SYS_PACKAGE_DOT@", ".working", NotificationManager.IMPORTANCE_NONE);
mgr.createNotificationChannel(channel);
Notification.Builder mknote = make_notification_template()
.setChannelId("@SYS_PACKAGE_DOT@")
.setCategory(Notification.CATEGORY_SERVICE);
startForeground(notificationIsRunningId, mknote.build());
return;
}
/* end of IF_ANDROIDAPI_GT_25 */
keepAwake_LT_API26();
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void onCreate() {
// Log.d("","LambdaNativeForegroundService created");
super.onCreate();
keepAwake();
}
@Override
public void onStart(Intent intent, int startId) {
// Log.d("","LambdaNativeForegroundService starting");
}
@Override public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onDestroy() {
// running=false;
// Log.d("","LambdaNativeForegroundService stopped");
}
// This is bound in the main class only!!! native void nativeEvent(int t, int x, int y);
}
17 changes: 17 additions & 0 deletions modules/androidforeground/ANDROID_xml_permissions
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<uses-feature android:name="android.permission.FOREGROUND_SERVICE" android:required="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" android:required="false" />
<!--

With API level 26 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS might be
appropriate to enable services to continuesly run.

However: Google is reported to remove apps needing this permission:
https://commonsware.com/blog/2015/11/11/google-anti-trust-issues.html

If this is bothering you, remove this comment and the permission below
and modify ANDROID_java_activityadditions to use the alternative,
- though rather impractical - method.

-->
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" android:required="false" />

1 change: 1 addition & 0 deletions modules/androidforeground/ANDROID_xml_services
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<service android:name=".LambdaNativeForegroundService" android:enabled="true" />
37 changes: 37 additions & 0 deletions modules/androidforeground/androidforeground.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
;; this module creates an android service to drive the native lambdanative payload in the background

;; Usage:
;;
;; (foreground-service! #t) ;; start service
;;
;; (foreground-service! #f) ;; stop service

(c-declare "int android_start_ln_foreground_service();")
(c-declare "int android_stop_ln_foreground_service();")

(define foreground-service!
(let ((running #f)
(start! (c-lambda () int "
#if defined(__ANDROID__)
___return(android_start_ln_foreground_service());
#else
___return(0);
#endif
"))
(stop! (c-lambda () int "
#if defined(__ANDROID__)
___return(android_stop_ln_foreground_service());
#else
___return(0);
#endif
")))
(lambda (flag)
(cond
((and flag (not running))
(set! running #t)
(let ((result (start!)))
(when (negative? result) (log-error "foreground-service! failed to start " result))))
((and (not flag) running)
(set! running #f)
(let ((result (stop!)))
(when (negative? result) (log-error "foreground-service! failed to stop " result))))))))