Skip to content

Commit

Permalink
initial commit based on the work of sven ströher
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielAW committed Oct 25, 2017
1 parent fc3492c commit 1737da8
Show file tree
Hide file tree
Showing 205 changed files with 19,432 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/.gitignore
@@ -0,0 +1 @@
/build
33 changes: 33 additions & 0 deletions app/build.gradle
@@ -0,0 +1,33 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "stroeher.sven.bluetooth_le_scanner"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.settings_workactivity.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.github.scribejava:scribejava-apis:4.1.1'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
testCompile 'junit:junit:4.12'
}
Binary file added app/libs/commons-lang-2.6.jar
Binary file not shown.
Binary file added app/libs/commons-logging-1.2.jar
Binary file not shown.
Binary file added app/libs/joda-time-2.4.jar
Binary file not shown.
Binary file added app/libs/json-lib-2.4-jdk15.jar
Binary file not shown.
Binary file added app/libs/servlet-api-2.5.jar
Binary file not shown.
Binary file added app/libs/spongycastle_core-1.56.0.0.jar
Binary file not shown.
25 changes: 25 additions & 0 deletions app/proguard-rules.pro
@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Sven\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
53 changes: 53 additions & 0 deletions app/src/main/AndroidManifest.xml
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="stroeher.sven.bluetooth_le_scanner">

<uses-sdk android:maxSdkVersion="21"/>

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false"/>
<!-- Only needed for Android 5.0 (API level 21) or higher. -->
<uses-feature
android:name="android.hardware.location.network"
android:required="true"/>
<uses-feature
android:name="android.hardware.location.gps"
android:required="true"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".activities.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".activities.WorkActivity"
android:label="WorkActivity"
android:parentActivityName=".activities.ScanActivity"
android:screenOrientation="portrait"/>
<activity
android:name=".activities.ScanActivity"
android:label="WorkActivity"
android:parentActivityName=".activities.MainActivity"
android:screenOrientation="portrait"/>
</application>

</manifest>
Binary file added app/src/main/ic_launcher-web.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
239 changes: 239 additions & 0 deletions app/src/main/java/com/fitbit/api/APIUtil.java
@@ -0,0 +1,239 @@
package com.fitbit.api;

import com.fitbit.api.client.http.OAuth;
import com.fitbit.api.common.model.timeseries.TimeSeriesResourceType;
import com.fitbit.api.model.APICollectionType;
import com.fitbit.api.model.APIFormat;
import com.fitbit.api.model.APIVersion;
import com.fitbit.api.model.ApiCollectionProperty;
import com.fitbit.api.model.FitbitResourceOwner;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.UUID;

public class APIUtil {

private static final Log log = LogFactory.getLog(APIUtil.class);

public static final String SIGNATURE_HEADER_NAME = "X-Fitbit-Signature";
public static final String UNSPECIFIED_SUBSCRIPTION_ID = "";

protected static final int TYPICAL_URL_LENGTH = 70;
protected static final String[] DATE_FORMATS = new String[] { "yyyy-MM-dd", "yyyy-MM" };
protected static final int STREAM_BUFFER_SIZE = 1024;


public static String constructFullUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, LocalDate date, APIFormat format) {
return nullSafeConstructUrl(baseUrl, version, owner, collectionType, date, null, format);
}

public static String constructFullUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, ApiCollectionProperty collectionProperty, APIFormat format) {
return nullSafeConstructUrl(baseUrl, version, owner, collectionType, collectionProperty, format);
}

public static String constructFullSubscriptionUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, APIFormat format) {
return constructFullSubscriptionUrl(baseUrl, version, owner, collectionType, UNSPECIFIED_SUBSCRIPTION_ID, format);
}

public static String constructFullSubscriptionUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, String subscriptionId, APIFormat format) {
return nullSafeConstructUrl(baseUrl, version, owner, collectionType, null, subscriptionId, format);
}

public static String constructRelativeUrl(FitbitResourceOwner owner, APICollectionType collectionType, LocalDate date) {
return nullSafeConstructRelativeUrl(owner, collectionType, date, null);
}

public static String contextualizeUrl(String baseUrl, APIVersion version, String relativeUrl, APIFormat format) {
return nullSafeContextualizeUrl(baseUrl, version, relativeUrl, format);
}

/**
* Parses the given date string into a valid {@link LocalDate} object,
* suitable for passing into many API methods.
*
* @param date
* @return
* @throws IllegalArgumentException if the given date can not be parsed
*/
public static LocalDate parseDate(String date) {
if (null==date || date.length() < 1) {
throw new IllegalArgumentException("Invalid empty input.");
}

LocalDate result = null;

for (String format : DATE_FORMATS) {
if (date.length()==format.length()) {
try {
long time = DateTimeFormat.forPattern(format).parseMillis(date);
result = new LocalDate(time);
break;
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Pattern '" + format + "' does not match date input '" + date + "': " + e);
}
}
}
}

if (null==result) {
throw new IllegalArgumentException("Invalid input date: '" + date + "'");
}

return result;
}


// TEST API inputStreamToString
public static String inputStreamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();

Reader reader = new InputStreamReader(is);

char[] buffer = new char[STREAM_BUFFER_SIZE];
int count;
while ((count = reader.read(buffer)) > 0) {
sb.append(buffer, 0, count);
}

return sb.toString();
}


public static String generateSignature(String data, String secret) {
OAuth oauth = new OAuth(null, secret);
return oauth.generateSignature(data);
}


/* ********************************************************************* */

protected static String nullSafeConstructUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, LocalDate date, String subscriptionId, APIFormat format) {
return
nullSafeContextualizeUrl(
baseUrl,
version,
nullSafeConstructRelativeUrl(
owner,
collectionType,
date,
subscriptionId
),
format
);
}

protected static String nullSafeConstructUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, APICollectionType collectionType, ApiCollectionProperty collectionProperty, APIFormat format) {
return
nullSafeContextualizeUrl(
baseUrl,
version,
nullSafeConstructRelativeUrl(
owner,
collectionType,
collectionProperty
),
format
);
}

private static String nullSafeConstructRelativeUrl(FitbitResourceOwner owner, APICollectionType collectionType, ApiCollectionProperty collectionProperty) {
StringBuilder sb = new StringBuilder(TYPICAL_URL_LENGTH);

if (null!=owner) {
sb.append("/" + owner.getResourceOwnerType().name() + "/" + owner.getId());
}
if (null!=collectionType) {
sb.append("/" + collectionType.getUrlPath());
}
if (null!=collectionProperty) {
sb.append("/" + collectionProperty);
}

return sb.toString();
}


protected static String nullSafeConstructRelativeUrl(FitbitResourceOwner owner, APICollectionType collectionType, LocalDate date, String subscriptionId) {
StringBuilder sb = new StringBuilder(TYPICAL_URL_LENGTH);

if (null!=owner) {
sb.append("/" + owner.getResourceOwnerType().name() + "/" + owner.getId());
}
if (null!=collectionType) {
if( null!= subscriptionId ) {
sb.append("/"+collectionType.getSubscriptionPath());
} else {
sb.append("/" + collectionType.getUrlPath());
}
}
if (null!=date) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
sb.append("/date/" + formatter.print(date));
}
if (null!=subscriptionId) {
sb.append("/apiSubscriptions");
if (! subscriptionId.equals(UNSPECIFIED_SUBSCRIPTION_ID)) {
sb.append("/" + subscriptionId);
}
}

return sb.toString();
}


protected static String nullSafeContextualizeUrl(String baseUrl, APIVersion version, String relativeUrl, APIFormat format) {
StringBuilder sb = new StringBuilder(TYPICAL_URL_LENGTH);

if (null!=baseUrl) {
sb.append(baseUrl);
}
if (null!=version) {
sb.append("/" + version.getVersion());
}
if (null!=relativeUrl) {
sb.append(relativeUrl);
}
if (null!=format) {
sb.append("." + format.toString().toLowerCase());
}

return sb.toString();
}

public static String constructTimeSeriesUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, TimeSeriesResourceType resourceType,
String startDate, String endDateOrPeriod, APIFormat format) {
return baseUrl + '/' + version.getVersion()
+ '/' + owner.getResourceOwnerType().name() + '/' + owner.getId()
+ resourceType.getResourcePath()
+ "/date/" + startDate
+ '/' + endDateOrPeriod
+ '.' + format.toString().toLowerCase();
}

public static String constructTimeSeriesUrl(String baseUrl, APIVersion version, FitbitResourceOwner owner, TimeSeriesResourceType resourceType,
String startDate, String endDateOrPeriod,
String startTime, String endTime, APIFormat format) {
return baseUrl + '/' + version.getVersion()
+ '/' + owner.getResourceOwnerType().name() + '/' + owner.getId()
+ resourceType.getResourcePath()
+ "/date/" + startDate
+ '/' + endDateOrPeriod
+ "/time/" + startTime
+ '/' + endTime
+ '.' + format.toString().toLowerCase();
}

public static String capitalize(String s) {
if (s == null || s.length() == 0) return s;
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
}
}

0 comments on commit 1737da8

Please sign in to comment.