Skip to content
Permalink
Browse files

Merge branch 'master' of github.com:dreeves/TagTime

  • Loading branch information...
dreeves committed Sep 2, 2018
2 parents 7bdb078 + 544f40f commit 59343e2cbe451eb16109e782c194ccbd0ee4196d
@@ -112,12 +112,17 @@ pings you entered last time. (Thanks to Paul Fenwick for implementing that.)
If your tagtime gap is g minutes then the probability of at least one ping
in any x minute window is 1-exp(-x/g).
The window corresponding to probability p is -g*ln(1-p).
The window corresponding to probability p is -g\*ln(1-p).
For example, with g=45, there's a 10% chance of getting pinged in any window
of duration 4 minutes 44 seconds.
There's a 50% chance of getting pinged within 31 minutes.
There's a 99% chance of a ping within 3.5 hours.
The probability of waiting over 10 hours for a ping is one in a million.
The probability of waiting over 10 hours\* for a ping is one in a million.
\* However, due to a [flaw in the random number generation algorithm used](http://github.com/dreeves/TagTime/issues/62#issuecomment-239705969) when this happens\*\*, the following ping will be more than 3 hours later.
\*\* Will not occur in the 21st century.
# Beeminder Integration
@@ -134,7 +139,7 @@ Regular expressions are encouraged!
See `settings.pl` for more details.
Note that TagTime sends times to Beeminder in hours.
Here's a handy tool if you like skating the edge of a TagTime-based Beeminder goal: [tminder](http://tminder.meteorapp.com/).
Here's a handy tool if you like skating the edge of a TagTime-based Beeminder goal: [tminder](http://mind.tagti.me).
**WARNING: TagTime will replace all existing data for the goal to make it match your TagTime log. In other words, your TagTime log is the master copy and TagTime will keep Beeminder in sync with it, including deleting data that's not found in your TagTime log.**
@@ -1,52 +1,13 @@
# Getting Started

To build the android app you first need to download and unpack the
android sdk. You can get that from http://developer.android.com/sdk
To build the android app you first need to download and install Android Studio. You can get that from http://developer.android.com/sdk

You should now have a directory `sdk/tools` which contains an `android`
binary. Add `sdk/tools` to your path:
You should now be able to run Android Studio. Do it.

$ export PATH="$PATH:/path/to/sdk/tools"
Now you need to configure a target. You can do this by clicking "SDK Manager" in the "Tools" menu. Select Android 4.3, which is API Level 18.

Now you need to configure a target. To list available targets run:

$ android list targets

By default this should have only one target, and it's probably for a
more recent version of Android than your test device. Open up the SDK
Manager so you can install an older target:

$ android

This should open up a GUI where you can download the files for an older
version of Android. `src/and/project.properties` has `target=android-4`
so check the box next to "Android 1.6 (API 4)" and click the "Install
Packages" button.

After you accept the license it will sit there with a progress bar going
through all the things it needs to download. When it finishes quit the
SDK Manager.

Listing targets again you should now see one available like:

$ android list targets
Available Android targets:
----------
id: 1 or "android-4"
Name: Android 1.6
...

Now we can configure our project to use this target:

$ cd TagTime/src/and
$ android update project --target android-4 --path .

This makes lots of changes, but the important one is that it creates
`build.xml` which allows you to run `ant`, which is kind of like `make`:

$ ant debug
[ lots of text ]
BUILD SUCCESSFUL
After that it will sit there with a progress bar going
through all the things it needs to download.

To run it on your phone you first need to enable usb debugging. If
you're running something older than 4.0 it's under
@@ -59,26 +20,13 @@ With usb debugging enabled, plug the phone into your computer. You
should see a notification on the phone like "Android debugging
enabled".

We now need to run `adb` which is in `platform-tools` and not `tools`,
so let's add it to the path:

$ export PATH="$PATH:/path/to/sdk/platform-tools"

Now we can run the app on the phone for testing:

$ adb -d install bin/TPController-debug.apk
Now return to Android Studio, and we can run the app on the phone for testing, by clicking "Run" in the "Run" menu.

If you already have TagTime installed on your phone it won't work:

Failure [INSTALL_FAILED_ALREADY_EXISTS]

You need to back up your Tagtime data and uninstall Tagtime first,
and then run the `adb` command again:

$ adb -d install bin/TPController-debug.apk
Success

Now you can go into Apps on your phone and start TagTime.
and then click "Run" again.

Note: You will need the latest version of ActionBarSherlock to compile
TagTime after recent updates.
Note: You will need to disable Instant Run to compile TagTime. You can do that by going to Android Studio settings and disabling everything in "Build, Execution, Deployment / Instant Run".
@@ -2,14 +2,16 @@
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.tools.build:gradle:3.1.2'
}
}

allprojects {
repositories {
jcenter()
google()
}
}
@@ -0,0 +1 @@
android.enableAapt2=false
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
@@ -1,8 +1,12 @@
apply plugin: 'com.android.library'

repositories {
jcenter()
google()
}

android {
compileSdkVersion 16
buildToolsVersion "22.0.1"
compileSdkVersion 18

defaultConfig {
minSdkVersion 8
@@ -1,13 +1,12 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 16
buildToolsVersion "22.0.1"
compileSdkVersion 23

defaultConfig {
applicationId "bsoule.tagtime"
minSdkVersion 8
targetSdkVersion 8
targetSdkVersion 23
}

buildTypes {
@@ -21,5 +20,8 @@ android {
dependencies {
compile project(':library')
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.android.support:support-v4:18.0.0'

// Stay in 22 as migration to 23 requires replacing ActionBarSherlock with ActionBarCompat
//noinspection GradleDependency,GradleCompatible
compile 'com.android.support:support-v4:22.2.1'
}
@@ -63,6 +63,12 @@
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<receiver
android:name=".SavePingReceiver"
android:enabled="true"
android:exported="false" />

</application>

</manifest>
@@ -1,11 +1,5 @@
package bsoule.tagtime;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -14,22 +8,31 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Parcel;
import android.os.PowerManager;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

/*
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/*
* the Ping service is in charge of maintaining random number
* generator state on disk, sending ping notifications, and
* setting ping alarms.
*
*
*/

public class PingService extends Service {
@@ -159,22 +162,25 @@ public void sendNote(long pingtime, long rowID) {
Date ping = new Date(pingtime * 1000);
CharSequence text = getText(R.string.status_bar_notes_ping_msg);

// Set the icon, scrolling text, and timestamp.
Notification note = new Notification(R.drawable.stat_ping, text, ping.getTime());

// The PendingIntent to launch our activity if the user selects this
// notification
Intent editIntent = new Intent(this, EditPing.class);
PendingIntent contentIntent = createPendingIntent(rowID, null);

editIntent.putExtra(PingsDbAdapter.KEY_ROWID, rowID);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Set the icon, scrolling text, and timestamp.
NotificationCompat.Builder noteBuilder =
new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.stat_ping)
.setTicker(text)
.setContentTitle("Ping!")
.setContentText(SDF.format(ping))
.setContentIntent(contentIntent)
.setWhen(ping.getTime());

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, editIntent, PendingIntent.FLAG_CANCEL_CURRENT);
addTagActions(noteBuilder, rowID);

// Set the info for the views that show in the notification panel.
// note.setLatestEventInfo(context, contentTitle, contentText,
// contentIntent)
note.setLatestEventInfo(this, "Ping!", SDF.format(ping), contentIntent);

Notification note = noteBuilder.build();

boolean suppress_noises = false;
if (mPrefs.getBoolean("pingQuietCharging", false)) {
@@ -212,16 +218,90 @@ public void sendNote(long pingtime, long rowID) {
// that gets assigned to the notification (we happen to pull it from a
// layout id
// so that we can cancel the notification later on).
assert NM != null;
NM.notify(PING_NOTES, note);

}

/**
* Create The PendingIntent to launch our activity if the user selects the notification
* caused by a ping. Optionally select a tag in the ping editor.
* @param rowID the ID of the ping
* @param tag the tag to select or {@code null}
* @return the PendingIntent
*/
private PendingIntent createPendingIntent(long rowID, String tag) {

Intent editIntent = new Intent(this, EditPing.class);

editIntent.putExtra(PingsDbAdapter.KEY_ROWID, rowID);
editIntent.putExtra(PingsDbAdapter.KEY_TAG, tag);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

return PendingIntent.getActivity(
this,
tag == null ? 0 : tag.hashCode(),
editIntent,
PendingIntent.FLAG_CANCEL_CURRENT
);
}

private PendingIntent createBroadcastPendingIntent(long rowID, String tag) {

Intent editIntent = new Intent(this, SavePingReceiver.class);

editIntent.putExtra(PingsDbAdapter.KEY_ROWID, rowID);
editIntent.putExtra(PingsDbAdapter.KEY_TAG, tag);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

return PendingIntent.getBroadcast(
this,
tag == null ? 0 : tag.hashCode(),
editIntent,
PendingIntent.FLAG_CANCEL_CURRENT
);
}

/**
* Add an action to a notification for each tag in the database. Handles
* opening/closing DB too.
*
* @param noteBuilder the builder that will create the notification
* @param rowId the ID of the ping that caused the notification
*/
private void addTagActions(NotificationCompat.Builder noteBuilder, long rowId) {
pingsDB = PingsDbAdapter.getInstance();
pingsDB.openDatabase();
Cursor cursor = pingsDB.fetchAllTags("FREQ");
cursor.moveToFirst();
int countActions = 0;
while (!cursor.isAfterLast() && countActions++ < 3) {
int index = cursor.getColumnIndex(PingsDbAdapter.KEY_TAG);
String name = cursor.getString(index);
PendingIntent pendingIntent = createBroadcastPendingIntent(rowId, name);
noteBuilder.addAction(0, name, pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
cursor.moveToNext();
}
pingsDB.closeDatabase();
}

// TODO: RTC_WAKEUP and appropriate perms into manifest
private void setAlarm(long PING) {
AlarmManager alarum = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent alit = new Intent(this, TPStartUp.class);
alit.putExtra("ThisIntentIsTPStartUpClass", true);
alarum.set(AlarmManager.RTC_WAKEUP, PING * 1000, PendingIntent.getBroadcast(this, 0, alit, 0));

assert alarum != null;
int type = AlarmManager.RTC_WAKEUP;
long trigger = PING * 1000;
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alit, 0);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarum.setExactAndAllowWhileIdle(type, trigger, pendingIntent);
} else {
alarum.set(type, trigger, pendingIntent);
}
}

private static final long IA = 16807;
Oops, something went wrong.

0 comments on commit 59343e2

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.