Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ pacemaker/pacemaker.iml
gradlew
gradlew.bat
local.properties
Pacemaker.iml
*.iml
18 changes: 17 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ android {
versionCode 1
versionName "1.0"
}

productFlavors {
demo1 {
applicationId "in.raveesh.pacemaker1"
}

demo2 {
applicationId "in.raveesh.pacemaker2"
}

demo3 {
applicationId "in.raveesh.pacemaker3"
}
}

buildTypes {
release {
minifyEnabled false
Expand All @@ -24,5 +39,6 @@ repositories {
}

dependencies {
compile 'in.raveesh:pacemaker:0.1.0-SNAPSHOT'
// compile 'in.raveesh:pacemaker:0.2.0-SNAPSHOT'
compile project(':pacemaker')
}
3 changes: 3 additions & 0 deletions demo/src/demo1/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Pacemaker1</string>
</resources>
3 changes: 3 additions & 0 deletions demo/src/demo2/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Pacemaker2</string>
</resources>
3 changes: 3 additions & 0 deletions demo/src/demo3/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Pacemaker3</string>
</resources>
25 changes: 11 additions & 14 deletions demo/src/main/java/in/raveesh/pacemaker/demo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,31 @@

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.View;
import android.widget.Button;

import in.raveesh.pacemaker.Pacemaker;
import in.raveesh.pacemaker.R;

public class MainActivity extends Activity {

boolean beginOrStop = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final Button set = (Button)findViewById(R.id.begin);
set.setOnClickListener(new View.OnClickListener() {
findViewById(R.id.begin).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!beginOrStop) {
Pacemaker.scheduleLinear(MainActivity.this, 5);
set.setText(R.string.stop);
}
else{
Pacemaker.cancelLinear(MainActivity.this, 5);
set.setText(R.string.begin);
}
beginOrStop = !beginOrStop;
public void onClick(@NonNull View v) {
Pacemaker.scheduleLinear(MainActivity.this, 5);
}
});
findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(@NonNull View v) {
Pacemaker.cancelLinear(MainActivity.this);
}
});

}
}
12 changes: 9 additions & 3 deletions demo/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context="in.raveesh.pacemaker.demo.MainActivity">
tools:context="in.raveesh.in.raveesh.pacemaker.demo.MainActivity">

<Button
android:id="@+id/begin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/begin" />
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop"/>

</RelativeLayout>
</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package in.raveesh.pacemaker;

import junit.framework.TestCase;

/**
* @author Badoo
*/
public class SchedulerTest extends TestCase {
private MyTimeProvider mTime;
private Scheduler mScheduler;

@Override
protected void setUp() throws Exception {
super.setUp();
mTime = new MyTimeProvider();
mScheduler = new Scheduler(mTime);
}

public void testEmpty() {
assertEquals(-1, mScheduler.getNextTriggerTime());
}

public void testOneRuleWithZeroTimeStart() {
mTime.time = 0;
mScheduler.addLinearPace("id", 100);
assertEquals(100, mScheduler.getNextTriggerTime());
mTime.time = 100;
assertEquals(200, mScheduler.getNextTriggerTime());
mTime.time = 150;
assertEquals(200, mScheduler.getNextTriggerTime());
}

public void testOneRuleWithNonZeroTimeStart() {
mTime.time = 100;
mScheduler.addLinearPace("id", 100);
assertEquals(200, mScheduler.getNextTriggerTime());
mTime.time = 200;
assertEquals(300, mScheduler.getNextTriggerTime());
mTime.time = 250;
assertEquals(300, mScheduler.getNextTriggerTime());
}

public void testOneRuleWithTimeCloseToEvent() {
mTime.time = 100;
mScheduler.addLinearPace("id", 100);
mTime.time = 199;
assertEquals(200, mScheduler.getNextTriggerTime());
mTime.time = 201;
assertEquals(300, mScheduler.getNextTriggerTime());
}

public void testInTwoRulesSmallerIsChoosen() {
mTime.time = 0;
mScheduler.addLinearPace("id1", 100);
mTime.time = 50;
mScheduler.addLinearPace("id2", 10);
assertEquals(60, mScheduler.getNextTriggerTime());
}


private class MyTimeProvider implements TimeProvider {
public long time;

@Override
public long getTime() {
return time;
}
}
}
23 changes: 23 additions & 0 deletions pacemaker/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="in.raveesh.heartbeater">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application android:allowBackup="true" android:label="@string/app_name">
<service
android:name="in.raveesh.pacemaker.PacemakerService"
android:enabled="true"
android:exported="false" />

<receiver
android:name="in.raveesh.pacemaker.PacemakerReceiver"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="in.raveesh.pacemaker.ACTION_MANAGE_PACEMAKER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</application>

</manifest>

This file was deleted.

72 changes: 21 additions & 51 deletions pacemaker/src/main/java/in/raveesh/pacemaker/Pacemaker.java
Original file line number Diff line number Diff line change
@@ -1,76 +1,46 @@
package in.raveesh.pacemaker;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
* Utility to add/remove paces which suppose to wake up GCM
*
* Several apps with this library will share responsibility to generate paces in battery efficient way:
* - Only one app will generate paces
* - When it is uninstalled, another will take responsibility
* - When device is restarted, paces will be recovered
*
* Only one pace delay is accepted from each app. If several apps requires different pace delays then shorter delay will take place
*
* Created by Raveesh on 23/07/15.
*
* Modifications made by Badoo 21/09/15
*/
public class Pacemaker {

public static final int TYPE_LINEAR = 1;
public static final int TYPE_EXPONENTIAL = 2;

public static final String KEY_DELAY = "KEY_DELAY";
public static final String KEY_TYPE = "KEY_TYPE";
public static final String KEY_MAX = "KEY_MAX";
static final String TAG = "Pacemaker";
static final boolean DEBUG = false;

/**
* Starts a linear repeated alarm that sends a broadcast to Play Services, which in turn sends a heartbeat
*
* Only one delay can be registered per one app. Each time you call to scheduleLinear, it will overload previous settings
*
* @param context Context from your application
* @param delay Gap between heartbeats in minutes
*/
public static void scheduleLinear(Context context, int delay) {
Intent intent = new Intent(context, HeartbeatReceiver.class);
intent.putExtra(KEY_DELAY, delay);
intent.putExtra(KEY_TYPE, TYPE_LINEAR);

long timeGap = delay * 60 * 1000;

PendingIntent alarmIntent = PendingIntent.getBroadcast(context, delay, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + timeGap, timeGap,
alarmIntent);
long delayInSec = delay * 60 * 1000;
Log.d("Heartbeater", "Scheduled repeating");
PacemakerService.Launcher.scheduleLinear(context, delayInSec);
}

/**
* Function to cancel your linear alarms if required
* @param context Context from your application
* @param delay Gap between heartbeats that you had set
*/
public static void cancelLinear(Context context, int delay){
Intent intent = new Intent(context, HeartbeatReceiver.class);
intent.putExtra(KEY_DELAY, delay);
intent.putExtra(KEY_TYPE, TYPE_LINEAR);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, delay, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(alarmIntent);
}

/**
* Starts an exponential alarm that sends a broadcast to Play Services, which in turn sends a heartbeat
* @param context Context from your application
* @param delay Time in which to send first broadcast. Subsequent broadcasts would be at exponential intervals
* @param max The max time till which the broadcasts should be sent. Once past this limit, no more heartbeats are sent
*/
public static void scheduleExponential(Context context, int delay, int max) {
Intent intent = new Intent(context, HeartbeatReceiver.class);
intent.putExtra(KEY_DELAY, delay);
intent.putExtra(KEY_TYPE, TYPE_EXPONENTIAL);
intent.putExtra(KEY_MAX, max);

long timeGap = delay * 60 * 1000;
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, delay, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + timeGap,
alarmIntent);
Log.d("Heartbeater", "Scheduled exponential");

public static void cancelLinear(Context context) {
Log.d("Heartbeater", "Cancelling repeating");
PacemakerService.Launcher.cancelLinear(context);
}
}
Loading