Skip to content
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

A ForegroundService for Lambdanative. #256

Closed
wants to merge 10 commits into from
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!))))))