Skip to content
Closed
21 changes: 21 additions & 0 deletions modules/androidforeground/ANDROID_c_additions
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* -*-C-*- */

void android_start_ln_foreground_service()
{
JNIEnv *env = GetJNIEnv();
jclass main_class = (*env)->FindClass(env, "@SYS_PACKAGE_SLASH@/@SYS_APPNAME@");
if (env&&globalObj){
jmethodID method = (*env)->GetMethodID(env, main_class, "startLnForegroundService", "()V");
(*env)->CallVoidMethod(env, globalObj, method);
}
}

void android_stop_ln_foreground_service()
{
JNIEnv *env = GetJNIEnv();
jclass main_class = (*env)->FindClass(env, "@SYS_PACKAGE_SLASH@/@SYS_APPNAME@");
if (env&&globalObj){
jmethodID method = (*env)->GetMethodID(env, main_class, "stopLnForegroundService", "()V");
(*env)->CallVoidMethod(env, globalObj, method);
}
}
6 changes: 6 additions & 0 deletions modules/androidforeground/ANDROID_c_defines
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* -*-C-*- */

void Java_@SYS_PACKAGE_UNDERSCORE@_LambdaNativeForegroundService_nativeEvent(JNIEnv* e, jobject o, jint t, jint x, jint y){
if ((*e)->ExceptionCheck(e)) return;
ffi_event((int)t,(int)x,(int)y);
}
31 changes: 31 additions & 0 deletions modules/androidforeground/ANDROID_java_activityadditions
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* -*-java-*- */
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));
}
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,76 @@
/* -*-java-*- */

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() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void onCreate() {
// Log.d("","LambdaNativeForegroundService created");
}
private void bgActivity() {
// Log.d("","LambdaNativeForegroundService started");
backgroundThread = new Thread() {
public void run() {
// setPriority(Thread.MAX_PRIORITY);
setPriority(Thread.MIN_PRIORITY);
while (running) {
// Log.d("", "LambdaNativeForegroundService EVENT_IDLE");
// nativeEvent(19,0,0); // EVENT_IDLE

// SystemClock.sleep(30000); // should be 30 seconds i.e. 30000 ms
try {
this.sleep(30000); // should be 30 seconds i.e. 30000 ms
try {
nativeEvent(19,0,0); // EVENT_IDLE
} catch (Throwable e) {
Log.e("LambdaNativeForegroundService", "exception: " + e.toString());
}
} catch (InterruptedException e) {}
}
// Log.d("","LambdaNativeForegroundService thread stopped");
}
};
backgroundThread.start();
}
@Override
public void onStart(Intent intent, int startId) {
// Log.d("","LambdaNativeForegroundService starting");

Notification notification = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
// .setContentText("TBD")
.setSmallIcon(R.drawable.icon)
// .setLargeIcon(aBitmap)
.setOngoing(true)
.build();

startForeground(notificationIsRunningId, notification);
bgActivity();
}
@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");
}
native void nativeEvent(int t, int x, int y);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* -*-java-*- */

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="false" />
<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" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" android:required="true" />
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" />
18 changes: 18 additions & 0 deletions modules/androidforeground/androidforeground.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
;; this module creates an android service to drive the native lambdanative payload in the background

(define foreground-service!
(let ((running #f)
(start! (c-lambda () void "
#if defined(__ANDROID__)
android_start_ln_foreground_service();
#endif
"))
(stop! (c-lambda () void "
#if defined(__ANDROID__)
android_stop_ln_foreground_service();
#endif
")))
(lambda (flag)
(cond
((and flag (not running)) (set! running #t) (start!))
((and (not flag) running) (set! running #f) (stop!))))))