Initial Android support
This commit is contained in:
parent
a782f8ffe9
commit
e4f6d7cd0b
32
plugin.xml
32
plugin.xml
@ -14,10 +14,12 @@
|
|||||||
|
|
||||||
<author>Sebastián Katzer</author>
|
<author>Sebastián Katzer</author>
|
||||||
|
|
||||||
|
<!-- cordova -->
|
||||||
<engines>
|
<engines>
|
||||||
<engine name="cordova" version=">=3.0.0" />
|
<engine name="cordova" version=">=3.0.0" />
|
||||||
</engines>
|
</engines>
|
||||||
|
|
||||||
|
<!-- js -->
|
||||||
<js-module src="www/background-mode.js" name="BackgroundMode">
|
<js-module src="www/background-mode.js" name="BackgroundMode">
|
||||||
<clobbers target="plugin.backgroundMode" />
|
<clobbers target="plugin.backgroundMode" />
|
||||||
</js-module>
|
</js-module>
|
||||||
@ -49,9 +51,37 @@
|
|||||||
|
|
||||||
<!-- android -->
|
<!-- android -->
|
||||||
<platform name="android">
|
<platform name="android">
|
||||||
<config-file target="config.xml" parent="/*">
|
<config-file target="res/xml/config.xml" parent="/*">
|
||||||
|
<feature name="BackgroundMode" >
|
||||||
|
<param name="android-package"
|
||||||
|
value="de.appplant.cordova.plugin.background.BackgroundMode"/>
|
||||||
|
</feature>
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<config-file target="res/xml/config.xml" parent="/*">
|
||||||
<preference name="KeepRunning" value="true" />
|
<preference name="KeepRunning" value="true" />
|
||||||
</config-file>
|
</config-file>
|
||||||
|
|
||||||
|
<config-file target="AndroidManifest.xml" parent="/manifest/application">
|
||||||
|
<!--
|
||||||
|
* Puts the service in a foreground state, where the system considers
|
||||||
|
* it to be something the user is actively aware of and thus not a
|
||||||
|
* candidate for killing when low on memory.
|
||||||
|
-->
|
||||||
|
<service
|
||||||
|
android:name="de.appplant.cordova.plugin.background.ForegroundService"
|
||||||
|
android:enabled="true" />
|
||||||
|
|
||||||
|
</config-file>
|
||||||
|
|
||||||
|
<source-file
|
||||||
|
src="src/android/BackgroundMode.java"
|
||||||
|
target-dir="src/de/appplant/cordova/plugin/background" />
|
||||||
|
|
||||||
|
<source-file
|
||||||
|
src="src/android/ForegroundService.java"
|
||||||
|
target-dir="src/de/appplant/cordova/plugin/background" />
|
||||||
|
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
<!-- wp8 -->
|
<!-- wp8 -->
|
||||||
|
180
src/android/BackgroundMode.java
Normal file
180
src/android/BackgroundMode.java
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-2014 appPlant UG
|
||||||
|
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.appplant.cordova.plugin.background;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.apache.cordova.CallbackContext;
|
||||||
|
import org.apache.cordova.CordovaPlugin;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
public class BackgroundMode extends CordovaPlugin {
|
||||||
|
|
||||||
|
// Flag indicates if the app is in background or foreground
|
||||||
|
private boolean inBackground = false;
|
||||||
|
|
||||||
|
// Flag indicates if the plugin is enabled or disabled
|
||||||
|
private boolean isDisabled = false;
|
||||||
|
|
||||||
|
// Used to (un)bind the service to with the activity
|
||||||
|
private ServiceConnection connection = new ServiceConnection() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||||
|
// Nothing to do here
|
||||||
|
Log.d("BackgroundMode", "Service connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
Log.w("BackgroundMode", "Service disrupted");
|
||||||
|
//stopService();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the request.
|
||||||
|
*
|
||||||
|
* @param action The action to execute.
|
||||||
|
* @param args The exec() arguments.
|
||||||
|
* @param callback The callback context used when
|
||||||
|
* calling back into JavaScript.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Returning false results in a "MethodNotFound" error.
|
||||||
|
*
|
||||||
|
* @throws JSONException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean execute (String action, JSONArray args,
|
||||||
|
CallbackContext callback) throws JSONException {
|
||||||
|
|
||||||
|
if (action.equalsIgnoreCase("observeLifeCycle")) {
|
||||||
|
// Nothing to do here
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.equalsIgnoreCase("enable")) {
|
||||||
|
enableMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.equalsIgnoreCase("disable")) {
|
||||||
|
disableMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the system is about to start resuming a previous activity.
|
||||||
|
*
|
||||||
|
* @param multitasking
|
||||||
|
* Flag indicating if multitasking is turned on for app
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onPause(boolean multitasking) {
|
||||||
|
super.onPause(multitasking);
|
||||||
|
inBackground = true;
|
||||||
|
startService();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the activity will start interacting with the user.
|
||||||
|
*
|
||||||
|
* @param multitasking
|
||||||
|
* Flag indicating if multitasking is turned on for app
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onResume(boolean multitasking) {
|
||||||
|
super.onResume(multitasking);
|
||||||
|
inBackground = false;
|
||||||
|
stopService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
stopService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the background mode.
|
||||||
|
*/
|
||||||
|
private void enableMode() {
|
||||||
|
isDisabled = false;
|
||||||
|
|
||||||
|
if (inBackground) {
|
||||||
|
startService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the background mode.
|
||||||
|
*/
|
||||||
|
private void disableMode() {
|
||||||
|
stopService();
|
||||||
|
isDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the activity to a background service and put them into foreground
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
private void startService() {
|
||||||
|
Activity context = cordova.getActivity();
|
||||||
|
|
||||||
|
Intent intent = new Intent(
|
||||||
|
context, ForegroundService.class);
|
||||||
|
|
||||||
|
if (isDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
context.bindService(
|
||||||
|
intent, connection, Context.BIND_AUTO_CREATE);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the activity to a background service and put them into foreground
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
private void stopService() {
|
||||||
|
Activity context = cordova.getActivity();
|
||||||
|
|
||||||
|
Intent intent = new Intent(
|
||||||
|
context, ForegroundService.class);
|
||||||
|
|
||||||
|
context.unbindService(connection);
|
||||||
|
context.stopService(intent);
|
||||||
|
}
|
||||||
|
}
|
164
src/android/ForegroundService.java
Normal file
164
src/android/ForegroundService.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-2014 appPlant UG
|
||||||
|
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.appplant.cordova.plugin.background;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the service in a foreground state, where the system considers it to be
|
||||||
|
* something the user is actively aware of and thus not a candidate for killing
|
||||||
|
* when low on memory.
|
||||||
|
*/
|
||||||
|
public class ForegroundService extends Service {
|
||||||
|
|
||||||
|
// Fixed ID for the 'foreground' notification
|
||||||
|
private static final int NOTIFICATION_ID = -574543954;
|
||||||
|
|
||||||
|
// Scheduler to exec periodic tasks
|
||||||
|
final Timer scheduler = new Timer();
|
||||||
|
|
||||||
|
// Used to keep the app alive
|
||||||
|
TimerTask keepAliveTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow clients to call on to the service.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IBinder onBind (Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put the service in a foreground state to prevent app from being killed
|
||||||
|
* by the OS.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onCreate () {
|
||||||
|
super.onCreate();
|
||||||
|
keepAwake();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
sleepWell();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put the service in a foreground state to prevent app from being killed
|
||||||
|
* by the OS.
|
||||||
|
*/
|
||||||
|
public void keepAwake() {
|
||||||
|
final Handler handler = new Handler();
|
||||||
|
|
||||||
|
startForeground(NOTIFICATION_ID, makeNotification());
|
||||||
|
|
||||||
|
keepAliveTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// Nothing to do here
|
||||||
|
// Log.d("BackgroundMode", "" + new Date().getTime());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scheduler.schedule(keepAliveTask, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop background mode.
|
||||||
|
*/
|
||||||
|
private void sleepWell() {
|
||||||
|
stopForeground(true);
|
||||||
|
keepAliveTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a notification as the visible part to be able to put the service
|
||||||
|
* in a foreground state.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A local ongoing notification which pending intent is bound to the
|
||||||
|
* main activity.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private Notification makeNotification() {
|
||||||
|
Context context = getApplicationContext();
|
||||||
|
String pkgName = context.getPackageName();
|
||||||
|
Intent intent = context.getPackageManager()
|
||||||
|
.getLaunchIntentForPackage(pkgName);
|
||||||
|
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(
|
||||||
|
context, NOTIFICATION_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
|
String title = "App is running in background";
|
||||||
|
|
||||||
|
Notification.Builder notification = new Notification.Builder(context)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(title)
|
||||||
|
.setTicker(title)
|
||||||
|
.setOngoing(true)
|
||||||
|
.setSmallIcon(getIconResId())
|
||||||
|
.setContentIntent(contentIntent);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < 16) {
|
||||||
|
// Build notification for HoneyComb to ICS
|
||||||
|
return notification.getNotification();
|
||||||
|
} else {
|
||||||
|
// Notification for Jellybean and above
|
||||||
|
return notification.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the resource ID of the app icon.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The resource ID of the app icon
|
||||||
|
*/
|
||||||
|
private int getIconResId () {
|
||||||
|
Context context = getApplicationContext();
|
||||||
|
Resources res = context.getResources();
|
||||||
|
String pkgName = context.getPackageName();
|
||||||
|
|
||||||
|
int resId;
|
||||||
|
resId = res.getIdentifier("icon", "drawable", pkgName);
|
||||||
|
|
||||||
|
return resId;
|
||||||
|
}
|
||||||
|
}
|
@ -46,4 +46,6 @@ BackgroundMode.prototype = {
|
|||||||
|
|
||||||
var plugin = new BackgroundMode();
|
var plugin = new BackgroundMode();
|
||||||
|
|
||||||
|
document.addEventListener("backbutton", function () {}, false);
|
||||||
|
|
||||||
module.exports = plugin;
|
module.exports = plugin;
|
Loading…
Reference in New Issue
Block a user