Initial open source release

This commit is contained in:
Trevor Slocum 2015-10-13 18:09:33 -07:00
commit 43d5d6d9e8
869 changed files with 24998 additions and 0 deletions

42
.gitignore vendored Normal file
View File

@ -0,0 +1,42 @@
build/
captures/
*/captures/
# built application files
*.apk
*.ap_
*.bar
*.wrn
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
# Local configuration file (sdk path, etc)
local.properties
# Eclipse project files
.classpath
.project
# Android Studio
.idea/
.gradle
/*/local.properties
/*/out
/*/*/build
*/build
/*/*/production
*.iml
*.iws
*.ipr
*~
*.swp

1
MeditationAssistant/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1 @@
{"project_info":{"project_id":"api-project-163346957857","project_number":"163346957857","name":"Meditation Assistant Free"},"client":[{"client_info":{"client_id":"android:sh.ftp.rocketninelabs.meditationassistant","client_type":1,"android_client_info":{"package_name":"sh.ftp.rocketninelabs.meditationassistant"}},"oauth_client":[{"client_id":"163346957857.apps.googleusercontent.com","client_type":1,"android_info":{"package_name":"sh.ftp.rocketninelabs.meditationassistant","certificate_hash":"f5f29854d4bac9d7ccf5d98a8a4b88f3beca47ff"}}],"services":{"analytics_service":{"status":2,"analytics_property":{"tracking_id":"UA-71983-51"}},"cloud_messaging_service":{"status":1,"apns_config":[]},"appinvite_service":{"status":2,"other_platform_oauth_client":[]},"google_signin_service":{"status":2},"ads_service":{"status":1}}}],"ARTIFACT_VERSION":"1"}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<ignore path="build/**" />
</lint>

View File

@ -0,0 +1,216 @@
-verbose
# Begin optimizeproguard-optimize.txt:
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 25
-allowaccessmodification
-dontpreverify
-dontwarn android.webkit.**
-keep class com.google.android.gms.analytics.**
-keep class com.google.analytics.tracking.**
-dontwarn com.google.android.gms.analytics.**
-dontwarn com.google.analytics.tracking.**
-dontwarn com.google.android.gms.**
-keep class android.support.** { *; }
-keep interface android.support.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
-keep class com.actionbarsherlock.** {*;}
-keep class org.holoeverywhere.** {*;}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
-keepclassmembers class * extends com.actionbarsherlock.ActionBarSherlock {
<init>(android.app.Activity, int);
}
# Keep line numbers to alleviate debugging stack traces
# -renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
# The remainder of this file is identical to the non-optimized version
# of the Proguard configuration file (except that the other file has
# flags to turn off optimization).
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**
# End optimize
-keepattributes JavascriptInterface
-overloadaggressively
-allowaccessmodification
-keep public class sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback
-keep public class * implements sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback
-keepclassmembers class * implements sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback {
<methods>;
}
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
-keep public class com.crittercism.**
-keepclassmembers public class com.crittercism.* { *; }
# HoloEverywhere
-keep,allowshrinking,allowoptimization public class * extends ListView
-keep,allowoptimization class org.holoeverywhere.** {
public *;
protected *;
}
-keepclasseswithmembernames class org.holoeverywhere.internal.** {
public *;
protected *;
}
-keepclasseswithmembernames class org.holoeverywhere.internal.AlertController
-keep public class org.holoeverywhere.internal.AlertController.RecycleListView { *; }
-keep,allowshrinking,allowoptimization class org.holoeverywhere.** { *; }
-keep,allowshrinking,allowoptimization interface org.holoeverywhere.** { *; }
-keep,allowshrinking,allowoptimization public class * extends android.app.Application
-keep,allowshrinking,allowoptimization public class * extends android.app.Service
-keep,allowshrinking,allowoptimization public class * extends android.content.BroadcastReceiver
-keep,allowshrinking,allowoptimization public class * extends android.content.ContentProvider
-keep,allowshrinking,allowoptimization public class * extends android.app.backup.BackupAgentHelper
-keep,allowshrinking,allowoptimization public class * extends android.preference.Preference
-keep,allowshrinking,allowoptimization public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep,allowshrinking,allowoptimization class * { <methods>; }
-keepclasseswithmembernames,allowshrinking class * {
native <methods>;
}
-keepclasseswithmembers,allowshrinking class * {
public <init>(android.content.Context,android.util.AttributeSet);
public <init>(android.content.Context,android.util.AttributeSet,int);
}
-keepclassmembers class * {
public <init>(android.content.Context,android.util.AttributeSet);
public <init>(android.content.Context,android.util.AttributeSet,int);
}
# Google API Client
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
-keepclassmembers class * {
@com.google.api.client.util.Key <fields>;
}
# Needed by google-http-client-android when linking against an older platform version
-dontwarn com.google.api.client.extensions.android.**
# Needed by google-api-client-android when linking against an older platform version
-dontwarn com.google.api.client.googleapis.extensions.android.**
# End Google API Client

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="sh.ftp.rocketninelabs.meditationassistant"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="22"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name="sh.ftp.rocketninelabs.meditationassistant.MeditationAssistant"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/appName"
android:theme="@style/MeditationDarkTheme">
<!-- Comment both when releasing full -->
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIqq_HCa56eFzfQpNSwYUIIytAyO6bh4fFUFUcYA"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<!-- DON'T COMMENT BELOW -->
<meta-data
android:name="com.google.android.gms.analytics.globalConfigResource"
android:resource="@xml/analytics"/>
<!-- Services -->
<service android:name="sh.ftp.rocketninelabs.meditationassistant.MeditationService"></service>
<!-- Receivers -->
<receiver
android:name="sh.ftp.rocketninelabs.meditationassistant.DailyNotification"
android:exported="true">
<intent-filter>
<action android:name="sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION"></action>
<action android:name="sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION_UPDATED"></action>
<action android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<data
android:path="sh.ftp.rocketninelabs.meditationassistant"
android:scheme="package"/>
</intent-filter>
</receiver>
<!-- Register AnalyticsReceiver and AnalyticsService to support background dispatching on non-Google Play devices -->
<receiver
android:name="com.google.android.gms.analytics.AnalyticsReceiver"
android:enabled="true"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH"/>
</intent-filter>
</receiver>
<service
android:name="com.google.android.gms.analytics.AnalyticsService"
android:enabled="true"
android:exported="false"/>
<!-- Register Wear data layer service -->
<service android:name=".WearListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER"/>
</intent-filter>
</service>
<!-- Widgets -->
<!--
<receiver
android:name="sh.ftp.rocketninelabs.meditationassistant.MeditationProvider1"
android:label="@string/widget1x1" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_1" />
</receiver>
<receiver
android:name="sh.ftp.rocketninelabs.meditationassistant.MeditationProvider2"
android:label="@string/widget2x1" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_2" />
</receiver>
<receiver
android:name="sh.ftp.rocketninelabs.meditationassistant.MeditationProvider3"
android:label="@string/widget3x1" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_3" />
</receiver>
-->
<!-- Activities -->
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.MainActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label="@string/appNameShort"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="sh.ftp.rocketninelabs.meditationassistant.ALARM"></action>
</intent-filter>
</activity>
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.SettingsActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label="@string/settings"
android:launchMode="singleTop"
android:parentActivityName="sh.ftp.rocketninelabs.meditationassistant.MainActivity"
tools:ignore="UnusedAttribute">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="sh.ftp.rocketninelabs.meditationassistant.MainActivity"/>
</activity>
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.MediNETActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label=""
android:launchMode="singleTop">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="sh.ftp.rocketninelabs.meditationassistant.MainActivity"/>
</activity>
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.CompleteActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label="@string/sessioncomplete">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="sh.ftp.rocketninelabs.meditationassistant.MainActivity"/>
</activity>
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.AboutActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label="@string/about">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="sh.ftp.rocketninelabs.meditationassistant.MainActivity"/>
</activity>
<activity
android:name="sh.ftp.rocketninelabs.meditationassistant.ProgressActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
android:label="@string/progress">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="sh.ftp.rocketninelabs.meditationassistant.MainActivity"/>
</activity>
<activity
android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="@android:style/Theme.Translucent"/>
</application>
</manifest>

View File

@ -0,0 +1,157 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.appinvite.AppInviteInvitation;
public class AboutActivity extends Activity {
public String license = "";
private MeditationAssistant ma = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(getMeditationAssistant().getMATheme());
getActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.activity_about);
TextView txtAboutAppName = (TextView) findViewById(R.id.txtAboutAppName);
TextView txtAboutAppVersion = (TextView) findViewById(R.id.txtAboutAppVersion);
if (getPackageName().equals(
"sh.ftp.rocketninelabs.meditationassistant")) {
txtAboutAppName.setText(getString(R.string.appName));
} else {
txtAboutAppName.setText(getString(R.string.appNameShort));
}
PackageInfo pInfo;
try {
pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
txtAboutAppVersion.setText(String.format(getString(R.string.version), pInfo.versionName));
} catch (PackageManager.NameNotFoundException e) {
txtAboutAppVersion.setVisibility(View.GONE);
e.printStackTrace();
}
LinearLayout layAbout = (LinearLayout) findViewById(R.id.layAbout);
layAbout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View arg0) {
ImageView charis = (ImageView) findViewById(R.id.charis);
charis.setVisibility(View.VISIBLE);
charis.startAnimation(AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.spin));
return true;
}
});
if (getMeditationAssistant().sendUsageReports()) {
getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.about, menu);
if (getMeditationAssistant().getIsBB() || !MeditationAssistant.getMarketName().equals("google")) {
MenuItem share = menu.findItem(R.id.action_share_app);
share.setVisible(false);
invalidateOptionsMenu();
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int i = item.getItemId();
if (i == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
return true;
} else if (i == R.id.action_share_app) {
Intent intent = new AppInviteInvitation.IntentBuilder(getString(R.string.appNameShort))
.setMessage(getString(R.string.invitationBlurb))
.build();
startActivityForResult(intent, 1337);
} else if (i == R.id.action_rate) {
getMeditationAssistant().askToRateApp();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStart() {
super.onStart();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}
public void sendMeEmail(View view) {
Log.d("MeditationAssistant", "Open about");
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("plain/text");
intent.putExtra(Intent.EXTRA_EMAIL,
new String[]{"tslocum@gmail.com"});
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(
getPackageName(), 0);
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.appNameShort) + " "
+ pInfo.versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.appNameShort));
}
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
startActivity(Intent.createChooser(intent, getString(R.string.sendEmail)));
}
public void openHowToMeditate(View view) {
startActivity(new Intent(
Intent.ACTION_VIEW,
Uri.parse("http://medinet.ftp.sh/howtomeditate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
public void openTranslate(View view) {
startActivity(new Intent(
Intent.ACTION_VIEW,
Uri.parse("http://medinet.ftp.sh/translate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.getApplication();
}
return ma;
}
}

View File

@ -0,0 +1,304 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TextView;
import java.util.Calendar;
import java.util.Locale;
public class CalendarFragment extends Fragment {
GridView gridCalendar = null;
TextView txtCurrentMonth = null;
TextView txtCurrentYear = null;
MonthAdapter monthadapter = null;
Calendar mCalendar = null;
ImageButton nextMonth = null;
private MeditationAssistant ma = null;
SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("sessionsupdate")) {
Log.d("MeditationAssistant", "Got sessions update, refreshing CalendarFragment");
refreshMonthDisplay();
}
}
};
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) getActivity().getApplication();
}
return ma;
}
private MonthAdapter getMonthAdapter() {
final DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
updatecurrentDate();
return new MonthAdapter(getActivity(), mCalendar.get(Calendar.MONTH),
mCalendar.get(Calendar.YEAR), metrics, (ProgressActivity) getActivity(), getMeditationAssistant());
}
public void refreshMonthDisplay() {
gridCalendar.setAdapter(getMonthAdapter());
}
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
int color_primary = getResources().getColor(getMeditationAssistant().getMATextColor(true));
int color_primary_disabled = getResources().getColor(getMeditationAssistant().getMATextColor(false));
/* Getting resource not found errors here */
try {
color_primary = getResources().getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.textColorPrimary})
.getResourceId(0, 0)
);
color_primary_disabled = getResources()
.getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant()
.getMATheme(),
new int[]{android.R.attr.textColorPrimaryDisableOnly}
)
.getResourceId(0, 0)
);
} catch (Exception e) {
Log.d("MeditationAssistant", "Unable to get color resources in CalendarFragment:");
e.printStackTrace();
}
txtCurrentMonth = new TextView(getActivity());
txtCurrentYear = new TextView(getActivity());
mCalendar = Calendar.getInstance();
txtCurrentMonth.setTextSize(22);
txtCurrentYear.setTextSize(12);
txtCurrentMonth.setTextColor(color_primary);
txtCurrentMonth
.setTextColor(color_primary_disabled);
txtCurrentMonth.setSingleLine(true);
txtCurrentMonth.setEllipsize(TextUtils.TruncateAt.END);
txtCurrentYear.setSingleLine(true);
txtCurrentYear.setEllipsize(TextUtils.TruncateAt.END);
gridCalendar = new GridView(getActivity());
gridCalendar.setNumColumns(7);
gridCalendar.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
gridCalendar.setVerticalSpacing(2);
gridCalendar.setHorizontalSpacing(2);
gridCalendar.setAdapter(getMonthAdapter());
}
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Context ctx = getActivity().getApplicationContext();
LinearLayout lcontainer = new LinearLayout(ctx);
lcontainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
lcontainer.setOrientation(LinearLayout.VERTICAL);
LinearLayout lmain = new LinearLayout(ctx);
lmain.setOrientation(LinearLayout.VERTICAL);
lmain.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
lmain.setWeightSum(0.5f);
LinearLayout lhoriz = new LinearLayout(ctx);
lhoriz.setOrientation(LinearLayout.HORIZONTAL);
lhoriz.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
lmain.addView(gridCalendar);
ImageButton prevMonth = new ImageButton(getActivity());
prevMonth.setImageDrawable(getResources().getDrawable(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{R.attr.actionIconPreviousItem})
.getResourceId(0, 0)
));
nextMonth = new ImageButton(getActivity());
nextMonth.setImageDrawable(getResources().getDrawable(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{R.attr.actionIconNextItem})
.getResourceId(0, 0)
));
/*TableLayout.LayoutParams monthbuttonslp = new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f);*/
TableLayout.LayoutParams monthbuttonslp = new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1f);
monthbuttonslp.setMargins(0, MeditationAssistant.dpToPixels(7, ctx), 0,
MeditationAssistant.dpToPixels(7, ctx));
prevMonth.setLayoutParams(monthbuttonslp);
nextMonth.setLayoutParams(monthbuttonslp);
prevMonth.setBackgroundColor(getActivity().getResources().getColor(
android.R.color.transparent));
nextMonth.setBackgroundColor(getActivity().getResources().getColor(
android.R.color.transparent));
prevMonth.setBackgroundResource(getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.selectableItemBackground})
.getResourceId(0, 0));
nextMonth.setBackgroundResource(getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.selectableItemBackground})
.getResourceId(0, 0));
prevMonth.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mCalendar.add(Calendar.MONTH, -1);
gridCalendar.setAdapter(getMonthAdapter());
updateMonthScroll();
}
});
nextMonth.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mCalendar.add(Calendar.MONTH, 1);
gridCalendar.setAdapter(getMonthAdapter());
updateMonthScroll();
}
});
LinearLayout ldate = new LinearLayout(ctx);
ldate.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams lp_horiz = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f);
prevMonth.setLayoutParams(lp_horiz);
ldate.setLayoutParams(lp_horiz);
nextMonth.setLayoutParams(lp_horiz);
ldate.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL);
txtCurrentMonth.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL);
txtCurrentYear.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL);
ldate.addView(txtCurrentMonth);
ldate.addView(txtCurrentYear);
lhoriz.setMinimumHeight(MeditationAssistant.dpToPixels(48, ctx));
lhoriz.addView(prevMonth);
lhoriz.addView(ldate);
lhoriz.addView(nextMonth);
LinearLayout lbottom = new LinearLayout(ctx);
lmain.setOrientation(LinearLayout.VERTICAL);
lbottom.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
lbottom.setWeightSum(0.5f);
lbottom.setMinimumHeight(MeditationAssistant.dpToPixels(48, ctx));
lbottom.addView(lhoriz);
lmain.setGravity(Gravity.BOTTOM);
View divBottom = new View(ctx);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,
MeditationAssistant.dpToPixels(1, ctx));
lp.setMargins(MeditationAssistant.dpToPixels(7, ctx), 0,
MeditationAssistant.dpToPixels(7, ctx), 0);
divBottom.setLayoutParams(lp);
divBottom.setPadding(7, 0, 7, 0);
divBottom.setBackgroundDrawable(getResources().getDrawable(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.listDividerAlertDialog})
.getResourceId(0, 0)
));
lcontainer.addView(lbottom);
lcontainer.addView(divBottom);
lcontainer.addView(lmain);
updateMonthScroll();
return lcontainer;
}
public void updatecurrentDate() {
txtCurrentMonth.setText(String.format(Locale.getDefault(), "%tB", mCalendar));
txtCurrentYear.setText(String.format(Locale.getDefault(), "%tY", mCalendar));
}
private void updateMonthScroll() {
Calendar nowCalendar = Calendar.getInstance();
if (mCalendar.get(Calendar.MONTH) == nowCalendar.get(Calendar.MONTH)
&& mCalendar.get(Calendar.YEAR) == nowCalendar
.get(Calendar.YEAR)) {
nextMonth.setClickable(false);
nextMonth.setVisibility(View.INVISIBLE);
} else {
nextMonth.setClickable(true);
nextMonth.setVisibility(View.VISIBLE);
}
}
@Override
public void onPause() {
getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onPause();
}
@Override
public void onResume() {
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onResume();
}
}

View File

@ -0,0 +1,421 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.analytics.GoogleAnalytics;
public class CompleteActivity extends Activity {
private AdView av = null;
private MediaPlayer mMediaPlayer;
private MeditationAssistant ma;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
handler.removeCallbacks(this);
if (getMeditationAssistant().getMediNET().result.equals("posted")) {
getMeditationAssistant()
.shortToast(getString(R.string.sessionPosted));
finish();
} else if (getMeditationAssistant().getMediNET().result
.equals("alreadyposted")) {
getMeditationAssistant().longToast(getString(R.string.sessionAlreadyPosted));
} else if (getMeditationAssistant().getMediNET().status
.equals("failure")
&& getMeditationAssistant().getMediNET().result
.equals("corrupt")) {
getMeditationAssistant()
.longToast(
getString(R.string.sessionNotPosted));
} else {
handler.postDelayed(this, 2000);
}
}
};
private Runnable clearWakeLock = new Runnable() {
public void run() {
handler.removeCallbacks(clearWakeLock);
WakeLocker.release();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(getMeditationAssistant().getMATheme());
setContentView(R.layout.activity_complete);
getMeditationAssistant().hideNotification(); // Called twice because it seems to help
long timestamp = System.currentTimeMillis() / 1000;
if (getMeditationAssistant().getTimeStartMeditate() == 0
|| (timestamp - getMeditationAssistant().getTimeStartMeditate()) <= 0) {
// Reset timestamps for current session
getMeditationAssistant().setTimeStartMeditate(0);
getMeditationAssistant().setTimeToStopMeditate(0);
finish();
return;
}
setTheme(getMeditationAssistant().getMATheme());
/*if (getMeditationAssistant().getMATheme() != R.style.MADark) {
getWindow().setBackgroundDrawable(
getResources().getDrawable(
android.R.drawable.screen_background_light));
}*/
setContentView(R.layout.activity_complete);
getWindow().setWindowAnimations(0);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
Boolean manual = false;
if (getIntent().hasExtra("manual")) {
if (getIntent().getBooleanExtra("manual", false)) {
manual = true;
}
}
getMeditationAssistant().unsetNotificationControl();
getMeditationAssistant().hideNotification(); // Called twice because it seems to help
if (getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant")) {
Log.d("MeditationAssistant", "Fetching ad");
av = (AdView) findViewById(R.id.adViewSessionComplete);
av.setVisibility(View.VISIBLE);
com.google.android.gms.ads.AdRequest adRequest = new com.google.android.gms.ads.AdRequest.Builder()
.addTestDevice(com.google.android.gms.ads.AdRequest.DEVICE_ID_EMULATOR)
.build();
av.loadAd(adRequest);
}
EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage);
if (editSessionMessage.getText().toString().equals("")
&& getMeditationAssistant().getPrefs().getBoolean("pref_remembermessage", false)) {
editSessionMessage.setText(getMeditationAssistant().getPrefs().getString("lastmessage", ""));
}
editSessionMessage
.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage);
TextView editSessionMessageInfo = (TextView) findViewById(R.id.editSessionMessageInfo);
if (hasFocus) {
editSessionMessageInfo.setText(String
.valueOf(editSessionMessage.getText()
.length())
+ " / 160");
editSessionMessageInfo.setVisibility(View.VISIBLE);
} else {
editSessionMessageInfo.setVisibility(View.GONE);
}
}
});
editSessionMessage.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
TextView editSessionMessageInfo = (TextView) findViewById(R.id.editSessionMessageInfo);
editSessionMessageInfo.setText(String.valueOf(s.length())
+ " / 160");
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
});
if (getMeditationAssistant()
.getTimeStartMeditate() == 0) {
/* Getting null pointers on getTimeStartMeditate() */
Log.d("MeditationAssistant", "getTimeStartMeditate() was 0! Exiting AlarmReceiverActivity...");
finish();
return;
}
// Meditation Session
getMeditationAssistant().getMediNET().resetSession();
getMeditationAssistant().getMediNET().session.started = getMeditationAssistant()
.getTimeStartMeditate();
if (getMeditationAssistant().getTimerMode().equals("endat")) {
Log.d("MeditationAssistant", String.valueOf(Math.min(timestamp, getMeditationAssistant().getTimeToStopMeditate())) + " - "
+ String.valueOf(getMeditationAssistant().getTimeStartMeditate()) + " - " + String.valueOf(getMeditationAssistant().pausetime));
getMeditationAssistant().getMediNET().session.length = Math.min(timestamp, getMeditationAssistant().getTimeToStopMeditate())
- getMeditationAssistant().getTimeStartMeditate() - getMeditationAssistant().pausetime;
} else {
Log.d("MeditationAssistant", String.valueOf(timestamp) + " - "
+ String.valueOf(getMeditationAssistant().getTimeStartMeditate()) + " - " + String.valueOf(getMeditationAssistant().pausetime));
getMeditationAssistant().getMediNET().session.length = timestamp
- getMeditationAssistant().getTimeStartMeditate() - getMeditationAssistant().pausetime;
}
getMeditationAssistant().getMediNET().session.length += 7; // Add seven seconds to account for slow wake-ups
getMeditationAssistant().getMediNET().session.completed = timestamp;
// Reset timestamps for current session
getMeditationAssistant().setTimeStartMeditate(0);
getMeditationAssistant().setTimeToStopMeditate(0);
Log.d("MeditationAssistant",
"Session length: "
+ String.valueOf(getMeditationAssistant().getMediNET().session.length)
);
if (getMeditationAssistant().getMediNET().session.length > 0) {
TextView txtDuration = (TextView) findViewById(R.id.txtDuration);
txtDuration.setText(MediNET
.durationToTimerString(getMeditationAssistant()
.getMediNET().session.length, false));
String text_size = getMeditationAssistant().getPrefs().getString("pref_text_size", "normal");
if (text_size.equals("tiny")) {
txtDuration.setTextSize(85);
} else if (text_size.equals("small")) {
txtDuration.setTextSize(115);
} else if (text_size.equals("large")) {
txtDuration.setTextSize(175);
} else if (text_size.equals("extralarge")) {
txtDuration.setTextSize(200);
} else { // Normal
txtDuration.setTextSize(153);
}
if (!manual
&& !getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "")
.equals("none")) {
mMediaPlayer = null;
if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "").equals(
"custom")) {
String soundpath = getMeditationAssistant().getPrefs().getString(
"pref_meditation_sound_finish_custom", "");
if (!soundpath.equals("")) {
try {
mMediaPlayer = MediaPlayer.create(this,
Uri.parse(soundpath));
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
mMediaPlayer = MediaPlayer.create(this, MeditationSounds
.getMeditationSound(getMeditationAssistant().getPrefs().getString(
"pref_meditation_sound_finish", "")));
}
if (mMediaPlayer != null) {
mMediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
WakeLocker.release();
mp.release();
}
});
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer
.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(
MediaPlayer mp) {
mp.start();
}
});
//mMediaPlayer.prepareAsync();
} else {
handler.postDelayed(clearWakeLock, 5000);
}
}
}
if (getMeditationAssistant().sendUsageReports()) {
getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER);
}
if (!manual) {
getMeditationAssistant().vibrateDevice();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.complete, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
if (item.getItemId() == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void askDismiss() {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(getString(R.string.askDiscardText))
.setPositiveButton(getString(R.string.discard),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
finish();
}
}
).setNegativeButton(getString(R.string.cancel), null)
.show();
}
public void dismiss(View view) {
if (getMeditationAssistant().getPrefs().getBoolean("pref_askdismiss", true)) {
askDismiss();
} else {
finish();
}
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.getApplication();
}
return ma;
}
private String getSessionMessage() {
EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage);
return editSessionMessage.getText().toString().trim();
}
@Override
public void onBackPressed() {
if (getMeditationAssistant().getPrefs().getBoolean("pref_askdismiss", true)) {
askDismiss();
} else {
super.onBackPressed();
}
}
@Override
public void onDestroy() {
if (av != null) {
av.destroy();
}
if (mMediaPlayer != null) {
try {
mMediaPlayer.release();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
WakeLocker.release();
} catch (Exception e) {
e.printStackTrace();
}
handler.removeCallbacks(runnable);
super.onDestroy();
}
@Override
public void onPause() {
if (av != null) {
av.pause();
}
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (av != null) {
av.resume();
}
}
@Override
public void onStart() {
super.onStart();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}
public void postMediNET(View view) {
if (getMeditationAssistant().getMediNETKey() == "") {
getMeditationAssistant().showSignInDialog(this);
return;
}
saveLastMessage();
getMeditationAssistant().shortToast(getString(R.string.sessionPosting));
getMeditationAssistant().getMediNET().session.message = getSessionMessage();
getMeditationAssistant().getMediNET().postSession();
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, 5);
}
private void saveLastMessage() {
SharedPreferences.Editor editor = getMeditationAssistant().getPrefs().edit();
editor.putString("lastmessage", getSessionMessage());
editor.apply();
}
public void saveMediNET(View view) {
saveLastMessage();
getMeditationAssistant().getMediNET().session.message = getSessionMessage();
getMeditationAssistant().getMediNET().saveSession(false, false);
getMeditationAssistant().shortToast(getString(R.string.sessionSaved));
finish();
}
}

View File

@ -0,0 +1,123 @@
package sh.ftp.rocketninelabs.meditationassistant;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
//import org.apache.commons.codec.binary.Base64;
public class Crypt {
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
public Crypt() {
ivspec = new IvParameterSpec("fzsznzsjh2asdr7e".getBytes());
keyspec = new SecretKeySpec("jqx82h4ad6fzb4dk".getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
public static String bytesToHex(byte[] data) {
if (data == null) {
return null;
}
int len = data.length;
String str = "";
for (int i = 0; i < len; i++) {
if ((data[i] & 0xFF) < 16)
str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF);
else
str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
}
return str;
}
public static byte[] hexToBytes(String str) {
if (str == null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) {
buffer[i] = (byte) Integer.parseInt(
str.substring(i * 2, i * 2 + 2), 16);
}
return buffer;
}
}
private static String padString(String source) {
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
return source;
}
public byte[] decrypt(String code) throws Exception {
if (code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public String decryptToString(String code) throws Exception {
if (code == null || code.length() == 0)
throw new Exception("Empty string");
String decryptedstr = null;
try {
decryptedstr = new String(decrypt(code)).trim();
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return decryptedstr;
}
public byte[] encrypt(String text) throws Exception {
if (text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e) {
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
}

View File

@ -0,0 +1,163 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class DailyNotification extends BroadcastReceiver {
MeditationAssistant ma = null;
@Override
public void onReceive(Context context, Intent intent) {
try {
ma = (MeditationAssistant) context.getApplicationContext();
} catch (Exception e) {
e.printStackTrace();
return;
}
if (!getMeditationAssistant().getPrefs().getBoolean("pref_daily_reminder", false)) {
cancelReminder(context);
return; // The user has not enabled the daily reminder
}
Log.d("MeditationAssistant", "onReceive in DailyNotification");
if (intent != null && intent.getAction() != null && intent.getAction().equals(MeditationAssistant.ACTION_REMINDER)) { // otherwise, it was just an update
Log.d("MeditationAssistant", "Daily notification intent!");
SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy", Locale.US);
if (getMeditationAssistant().getTimeToStopMeditate() != 0) {
Log.d("MeditationAssistant", "Skipping daily notification today, session in progress...");
} else if (getMeditationAssistant().db.numSessionsByDate(sdf.format(Calendar.getInstance().getTime())) > 0) {
Log.d("MeditationAssistant", "Skipping daily notification today, there has already been a session recorded...");
} else {
long last_reminder = getMeditationAssistant().getPrefs().getLong("last_reminder", 0);
if (last_reminder == 0 || getMeditationAssistant().getTimestamp() - last_reminder > 120) {
getMeditationAssistant().getPrefs().edit().putLong("last_reminder", getMeditationAssistant().getTimestamp()).apply();
String reminderText = getMeditationAssistant().getPrefs().getString("pref_daily_reminder_text", "").trim();
if (reminderText.equals("")) {
reminderText = context.getString(R.string.reminderText);
}
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(context.getString(R.string.meditate))
.setContentText(reminderText)
.setTicker(reminderText)
.setAutoCancel(true);
if (getMeditationAssistant().getPrefs().getBoolean("pref_vibrate_reminder", true)) {
long[] vibrationPattern = {0, 200, 500, 200, 500};
notificationBuilder.setVibrate(vibrationPattern);
} else {
long[] vibrationPattern = {0, 0};
notificationBuilder.setVibrate(vibrationPattern);
}
if (getMeditationAssistant().getPrefs().getBoolean("pref_sound_reminder", true)) {
notificationBuilder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
}
Intent notificationIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
//Intent launchMain = new Intent(context, MainActivity.class);
//PendingIntent launchNotification = PendingIntent.getActivity(context, 1008, launchMain, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(resultPendingIntent);
Notification notification = notificationBuilder.build();
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1946, notification);
}
}
}
String reminderTime = ma.getPrefs().getString("pref_daily_reminder_time", "19:00");
String[] reminderTimeSplit = ((reminderTime != null && reminderTime != "") ? reminderTime : "19:00").split(":");
Integer reminderHour = Integer.valueOf(reminderTimeSplit[0]);
Integer reminderMinute = Integer.valueOf(reminderTimeSplit[1]);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, reminderHour);
calendar.set(Calendar.MINUTE, reminderMinute);
calendar.set(Calendar.SECOND, 0);
if (Calendar.getInstance().getTimeInMillis() > calendar.getTimeInMillis()) {
calendar.add(Calendar.DATE, 1); // Tomorrow
}
cancelReminder(context);
getMeditationAssistant().reminderPendingIntent = PendingIntent
.getBroadcast(
context,
1946,
new Intent(
MeditationAssistant.ACTION_REMINDER),
PendingIntent.FLAG_CANCEL_CURRENT
);
if (Build.VERSION.SDK_INT >= 19) {
getMeditationAssistant().reminderAlarmManager.setExact(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
getMeditationAssistant().reminderPendingIntent);
} else {
getMeditationAssistant().reminderAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000,
getMeditationAssistant().reminderPendingIntent);
}
Log.d("MeditationAssistant", "Set daily reminder alarm for " + calendar.toString());
}
private void cancelReminder(Context context) {
if (getMeditationAssistant().reminderPendingIntent != null) {
try {
getMeditationAssistant().reminderAlarmManager.cancel(getMeditationAssistant().reminderPendingIntent);
} catch (Exception e) {
Log.e("MeditationAssistant", "AlarmManager update was not canceled. " + e.toString());
}
try {
PendingIntent.getBroadcast(context, 0, new Intent(
MeditationAssistant.ACTION_REMINDER),
PendingIntent.FLAG_CANCEL_CURRENT
).cancel();
} catch (Exception e) {
Log.e("MeditationAssistant", "PendingIntent broadcast was not canceled. " + e.toString());
}
try {
getMeditationAssistant().reminderPendingIntent.cancel();
} catch (Exception e) {
Log.e("MeditationAssistant", "PendingIntent was not canceled. " + e.toString());
}
}
}
public MeditationAssistant getMeditationAssistant() {
return ma;
}
}

View File

@ -0,0 +1,374 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class DatabaseHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 4;
private static final String DATABASE_NAME = "meditationassistant";
private static final String TABLE_SESSIONS = "sessions";
// Column names
private static final String KEY_ID = "id";
private static final String KEY_ACCOUNT = "account";
private static final String KEY_STARTED = "started";
private static final String KEY_COMPLETED = "completed";
private static final String KEY_LENGTH = "length";
private static final String KEY_MESSAGE = "message";
private static final String KEY_DATE = "date";
private static final String KEY_ISPOSTED = "isposted";
private static final String KEY_STREAKDAY = "streakday";
private static DatabaseHandler databaseHandler;
private SQLiteDatabase db = null;
private MeditationAssistant ma = null;
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
ma = (MeditationAssistant) context;
db = this.getWritableDatabase();
}
public static synchronized DatabaseHandler getInstance(Context context) {
if (databaseHandler == null) {
databaseHandler = new DatabaseHandler(context.getApplicationContext());
}
return databaseHandler;
}
void addSession(SessionSQL session) {
ContentValues values = new ContentValues();
values.put(KEY_STARTED, session._started);
values.put(KEY_COMPLETED, session._completed);
values.put(KEY_LENGTH, session._length);
values.put(KEY_MESSAGE, session._message);
values.put(KEY_DATE, sessionToAPIDate(session));
values.put(KEY_ISPOSTED, session._isposted);
values.put(KEY_STREAKDAY, session._streakday);
db.insert(TABLE_SESSIONS, null, values);
getMeditationAssistant().recalculateMeditationStreak();
getMeditationAssistant().notifySessionsUpdated();
}
public String sessionToAPIDate(SessionSQL session) {
if (session._completed != null) {
return timestampToAPIDate(session._completed * 1000);
} else {
return timestampToAPIDate((session._started + session._length) * 1000);
}
}
public String timestampToAPIDate(long timestamp) {
SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy", Locale.US);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
Date api_date = cal.getTime();
return sdf.format(api_date);
}
public MeditationAssistant getMeditationAssistant() {
return ma;
}
public void deleteSession(SessionSQL session) {
db.delete(TABLE_SESSIONS, KEY_ID + " = ?",
new String[]{String.valueOf(session.getID())});
getMeditationAssistant().notifySessionsUpdated();
}
public ArrayList<SessionSQL> getAllSessions() {
ArrayList<SessionSQL> sessionList = new ArrayList<SessionSQL>();
String selectQuery = "SELECT * FROM `" + TABLE_SESSIONS + "` ORDER BY "
+ "`" + KEY_COMPLETED + "` DESC";
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
SessionSQL session = new SessionSQL(cursor.getLong(cursor
.getColumnIndex(KEY_ID)), cursor.getLong(cursor
.getColumnIndex(KEY_STARTED)), cursor.getLong(cursor
.getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor
.getColumnIndex(KEY_LENGTH)), cursor.getString(cursor
.getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor
.getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor
.getColumnIndex(KEY_STREAKDAY)));
sessionList.add(session);
} while (cursor.moveToNext());
}
cursor.close();
return sessionList;
}
public ArrayList<SessionSQL> getAllLocalSessions() {
ArrayList<SessionSQL> sessionList = new ArrayList<SessionSQL>();
String selectQuery = "SELECT * FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_ISPOSTED + "` = 0";
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
SessionSQL session = new SessionSQL(cursor.getLong(cursor
.getColumnIndex(KEY_ID)), cursor.getLong(cursor
.getColumnIndex(KEY_STARTED)), cursor.getLong(cursor
.getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor
.getColumnIndex(KEY_LENGTH)), cursor.getString(cursor
.getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor
.getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor
.getColumnIndex(KEY_STREAKDAY)));
sessionList.add(session);
} while (cursor.moveToNext());
}
cursor.close();
return sessionList;
}
public int getNumSessions() {
String countQuery = "SELECT COUNT(*) FROM `" + TABLE_SESSIONS + "`";
Cursor cursor = db.rawQuery(countQuery, null);
cursor.moveToFirst();
int numsessions = cursor.getInt(0);
cursor.close();
return numsessions;
}
public int getTotalTimeSpentMeditating() {
int time_meditating = 0;
Cursor cursor = db.rawQuery("SELECT SUM(`" + KEY_LENGTH + "`) FROM `" + TABLE_SESSIONS + "`", null);
if (cursor.moveToFirst()) {
time_meditating = cursor.getInt(0);
}
cursor.close();
return time_meditating;
}
int numSessionsByDate(String date) {
Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_DATE + "`=?", new String[]{date});
cursor.moveToFirst();
int numsessions = cursor.getInt(0);
cursor.close();
return numsessions;
}
int getLongestSessionLength() {
int longestsessionlength = 0;
Cursor cursor = db.rawQuery("SELECT MAX(`" + KEY_LENGTH + "`) FROM `" + TABLE_SESSIONS + "`", null);
if (cursor.moveToFirst()) {
longestsessionlength = cursor.getInt(0);
}
cursor.close();
return longestsessionlength;
}
SessionSQL getSessionByStarted(long started) {
SessionSQL session = null;
Cursor cursor = db.query(TABLE_SESSIONS, new String[]{KEY_ID,
KEY_STARTED, KEY_COMPLETED, KEY_LENGTH, KEY_MESSAGE, KEY_ISPOSTED, KEY_STREAKDAY},
KEY_STARTED + "=?", new String[]{String.valueOf(started)},
null, null, null, "1"
);
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
session = new SessionSQL(cursor.getLong(cursor
.getColumnIndex(KEY_ID)), cursor.getLong(cursor
.getColumnIndex(KEY_STARTED)), cursor.getLong(cursor
.getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor
.getColumnIndex(KEY_LENGTH)), cursor.getString(cursor
.getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor
.getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor
.getColumnIndex(KEY_STREAKDAY)));
}
cursor.close();
}
return session;
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("MeditationAssistant", "CREATING DATABASE VERSION " + String.valueOf(DATABASE_VERSION));
db.execSQL("CREATE TABLE `" + TABLE_SESSIONS + "` ("
+ "`" + KEY_ID + "` INTEGER PRIMARY KEY, "
+ "`" + KEY_STARTED + "` INTEGER, `" + KEY_COMPLETED + "` INTEGER, "
+ "`" + KEY_LENGTH + "` INTEGER, `" + KEY_MESSAGE + "` STRING, "
+ "`" + KEY_DATE + "` STRING, `" + KEY_ISPOSTED + "` INTEGER, `" + KEY_STREAKDAY + "` INTEGER" + ")");
db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)");
db.execSQL("CREATE INDEX `" + KEY_COMPLETED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_COMPLETED + "`)");
db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d("MeditationAssistant", "DATABASE UPGRADE INITIATED - Old: " + String.valueOf(oldVersion) + " New: " + String.valueOf(newVersion));
int curVer = oldVersion;
while (curVer < newVersion) {
curVer++;
switch (curVer) {
case 2:
Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer));
db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_STREAKDAY + "` INTEGER");
break;
case 3:
Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer));
/* Fix for incorrect upgrade code */
try {
db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_DATE + "` STRING");
} catch (Exception e) {
// Column already exists
}
db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)");
db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)");
break;
case 4:
Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer));
/* Fix for incorrect upgrade code */
try {
db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_STREAKDAY + "` INTEGER");
} catch (Exception e) {
// Column already exists
}
try {
db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_DATE + "` STRING");
db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)");
db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)");
} catch (Exception e) {
// Column already exists
}
db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_COMPLETED + "` INTEGER");
db.execSQL("CREATE INDEX `" + KEY_COMPLETED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_COMPLETED + "`)");
Cursor cursor = db.rawQuery("SELECT * FROM `" + TABLE_SESSIONS + "`", null);
if (cursor.moveToFirst()) {
long session_completed;
do {
try {
session_completed = cursor.getLong(cursor.getColumnIndex(KEY_COMPLETED));
} catch (Exception e) {
session_completed = 0;
Log.d("MeditationAssistant", "Error fetching completed:");
e.printStackTrace();
}
if (session_completed == 0) {
Log.d("MeditationAssistant", "UPDATE `" + TABLE_SESSIONS + "` SET `" + KEY_COMPLETED +
"`='" + (cursor.getLong(cursor.getColumnIndex(KEY_STARTED)) + cursor.getLong(cursor.getColumnIndex(KEY_LENGTH))) + "' WHERE `" + KEY_ID + "`='"
+ cursor.getLong(cursor.getColumnIndex(KEY_ID)) + "'");
db.rawQuery("UPDATE `" + TABLE_SESSIONS + "` SET `" + KEY_COMPLETED +
"`='" + (cursor.getLong(cursor.getColumnIndex(KEY_STARTED)) + cursor.getLong(cursor.getColumnIndex(KEY_LENGTH))) + "' WHERE `" + KEY_ID + "`='"
+ cursor.getLong(cursor.getColumnIndex(KEY_ID)) + "'", null);
}
} while (cursor.moveToNext());
}
cursor.close();
break;
}
}
}
public int updateSession(SessionSQL session) {
ContentValues values = new ContentValues();
values.put(KEY_STARTED, session._started);
values.put(KEY_COMPLETED, session._completed);
values.put(KEY_LENGTH, session._length);
values.put(KEY_MESSAGE, session._message);
values.put(KEY_ISPOSTED, session._isposted);
values.put(KEY_STREAKDAY, session._streakday);
int result = db.update(TABLE_SESSIONS, values, KEY_ID + " = ?",
new String[]{String.valueOf(session.getID())});
getMeditationAssistant().notifySessionsUpdated();
return result;
}
public SessionSQL getSessionByDate(String date) {
Log.d("MeditationAssistant", "SQL: get session by date " + date);
SessionSQL session = null;
Cursor cursor = db.query(TABLE_SESSIONS, new String[]{KEY_ID,
KEY_STARTED, KEY_COMPLETED, KEY_LENGTH, KEY_MESSAGE, KEY_ISPOSTED, KEY_STREAKDAY},
KEY_DATE + "=?", new String[]{date},
null, null, null, "1"
);
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
session = new SessionSQL(cursor.getLong(cursor
.getColumnIndex(KEY_ID)), cursor.getLong(cursor
.getColumnIndex(KEY_STARTED)), cursor.getLong(cursor
.getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor
.getColumnIndex(KEY_LENGTH)), cursor.getString(cursor
.getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor
.getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor
.getColumnIndex(KEY_STREAKDAY)));
}
cursor.close();
}
return session;
}
public ArrayList<SessionSQL> getSessionsByDate(String date) {
ArrayList<SessionSQL> sessionList = new ArrayList<SessionSQL>();
Cursor cursor = db.rawQuery("SELECT * FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_DATE + "`=? ORDER BY `" + KEY_STARTED + "` ASC", new String[]{date});
if (cursor.moveToFirst()) {
do {
SessionSQL session = new SessionSQL(cursor.getLong(cursor
.getColumnIndex(KEY_ID)), cursor.getLong(cursor
.getColumnIndex(KEY_STARTED)), cursor.getLong(cursor
.getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor
.getColumnIndex(KEY_LENGTH)), cursor.getString(cursor
.getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor
.getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor
.getColumnIndex(KEY_STREAKDAY)));
sessionList.add(session);
} while (cursor.moveToNext());
}
cursor.close();
return sessionList;
}
}

View File

@ -0,0 +1,27 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.view.View;
import android.view.animation.Animation;
public class FadeOutAnimationListener implements Animation.AnimationListener {
View view;
@Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
public void setView(View v) {
view = v;
}
}

View File

@ -0,0 +1,503 @@
package sh.ftp.rocketninelabs.meditationassistant;
/*
* Copyright (C) 2007-2008 OpenIntents.org
*
* Licensed 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.
*/
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
/**
* @author Peli
* @author paulburke (ipaulpro)
* @version 2013-12-11
*/
public class FileUtils {
public static final String MIME_TYPE_AUDIO = "audio/*";
public static final String MIME_TYPE_TEXT = "text/*";
public static final String MIME_TYPE_IMAGE = "image/*";
public static final String MIME_TYPE_VIDEO = "video/*";
public static final String MIME_TYPE_APP = "application/*";
public static final String HIDDEN_PREFIX = ".";
/**
* TAG for log messages.
*/
static final String TAG = "FileUtils";
private static final boolean DEBUG = false; // Set to true to enable logging
/**
* File and folder comparator.
*
* @author paulburke
*/
public static Comparator<File> sComparator = new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
// Sort alphabetically by lower case, which is much cleaner
return f1.getName().toLowerCase().compareTo(
f2.getName().toLowerCase());
}
};
/**
* File (not directories) filter.
*
* @author paulburke
*/
public static FileFilter sFileFilter = new FileFilter() {
@Override
public boolean accept(File file) {
final String fileName = file.getName();
// Return files only (not directories) and skip hidden files
return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
}
};
/**
* Folder (directories) filter.
*
* @author paulburke
*/
public static FileFilter sDirFilter = new FileFilter() {
@Override
public boolean accept(File file) {
final String fileName = file.getName();
// Return directories only and skip hidden directories
return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
}
};
private FileUtils() {
} //private constructor to enforce Singleton pattern
/**
* Gets the extension of a file name, like ".png" or ".jpg".
*
* @param uri
* @return Extension including the dot("."); "" if there is no extension;
* null if uri was null.
*/
public static String getExtension(String uri) {
if (uri == null) {
return null;
}
int dot = uri.lastIndexOf(".");
if (dot >= 0) {
return uri.substring(dot);
} else {
// No extension.
return "";
}
}
/**
* @return Whether the URI is a local one.
*/
public static boolean isLocal(String url) {
return (url != null && !url.startsWith("http://") && !url.startsWith("https://"));
}
/**
* @return True if Uri is a MediaStore Uri.
* @author paulburke
*/
public static boolean isMediaUri(Uri uri) {
return "media".equalsIgnoreCase(uri.getAuthority());
}
/**
* Convert File into Uri.
*
* @param file
* @return uri
*/
public static Uri getUri(File file) {
if (file != null) {
return Uri.fromFile(file);
}
return null;
}
/**
* Returns the path only (without file name).
*
* @param file
* @return
*/
public static File getPathWithoutFilename(File file) {
if (file != null) {
if (file.isDirectory()) {
// no file to be split off. Return everything
return file;
} else {
String filename = file.getName();
String filepath = file.getAbsolutePath();
// Construct path without file name.
String pathwithoutname = filepath.substring(0,
filepath.length() - filename.length());
if (pathwithoutname.endsWith("/")) {
pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
}
return new File(pathwithoutname);
}
}
return null;
}
/**
* @return The MIME type for the given file.
*/
public static String getMimeType(File file) {
String extension = getExtension(file.getName());
if (extension.length() > 0)
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));
return "application/octet-stream";
}
/**
* @return The MIME type for the give Uri.
*/
public static String getMimeType(Context context, Uri uri) {
File file = new File(getPath(context, uri));
return getMimeType(file);
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
* @author paulburke
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
* @author paulburke
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
* @author paulburke
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
* @author paulburke
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
if (DEBUG)
DatabaseUtils.dumpCursor(cursor);
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.<br>
* <br>
* Callers should check whether the path is local before assuming it
* represents a local file.
*
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
* @see #isLocal(String)
* @see #getFile(Context, Uri)
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
if (DEBUG)
Log.d(TAG + " File -",
"Authority: " + uri.getAuthority() +
", Fragment: " + uri.getFragment() +
", Port: " + uri.getPort() +
", Query: " + uri.getQuery() +
", Scheme: " + uri.getScheme() +
", Host: " + uri.getHost() +
", Segments: " + uri.getPathSegments().toString()
);
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Convert Uri into File, if possible.
*
* @return file A local file that the Uri was pointing to, or null if the
* Uri is unsupported or pointed to a remote resource.
* @author paulburke
* @see #getPath(Context, Uri)
*/
public static File getFile(Context context, Uri uri) {
if (uri != null) {
String path = getPath(context, uri);
if (path != null && isLocal(path)) {
return new File(path);
}
}
return null;
}
/**
* Get the file size in a human-readable string.
*
* @param size
* @return
* @author paulburke
*/
public static String getReadableFileSize(int size) {
final int BYTES_IN_KILOBYTES = 1024;
final DecimalFormat dec = new DecimalFormat("###.#");
final String KILOBYTES = " KB";
final String MEGABYTES = " MB";
final String GIGABYTES = " GB";
float fileSize = 0;
String suffix = KILOBYTES;
if (size > BYTES_IN_KILOBYTES) {
fileSize = size / BYTES_IN_KILOBYTES;
if (fileSize > BYTES_IN_KILOBYTES) {
fileSize = fileSize / BYTES_IN_KILOBYTES;
if (fileSize > BYTES_IN_KILOBYTES) {
fileSize = fileSize / BYTES_IN_KILOBYTES;
suffix = GIGABYTES;
} else {
suffix = MEGABYTES;
}
}
}
return String.valueOf(dec.format(fileSize) + suffix);
}
/**
* Attempt to retrieve the thumbnail of given File from the MediaStore. This
* should not be called on the UI thread.
*
* @param context
* @param file
* @return
* @author paulburke
*/
public static Bitmap getThumbnail(Context context, File file) {
return getThumbnail(context, getUri(file), getMimeType(file));
}
/**
* Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
* should not be called on the UI thread.
*
* @param context
* @param uri
* @return
* @author paulburke
*/
public static Bitmap getThumbnail(Context context, Uri uri) {
return getThumbnail(context, uri, getMimeType(context, uri));
}
/**
* Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
* should not be called on the UI thread.
*
* @param context
* @param uri
* @param mimeType
* @return
* @author paulburke
*/
public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
if (DEBUG)
Log.d(TAG, "Attempting to get thumbnail");
if (!isMediaUri(uri)) {
Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
return null;
}
Bitmap bm = null;
if (uri != null) {
final ContentResolver resolver = context.getContentResolver();
Cursor cursor = null;
try {
cursor = resolver.query(uri, null, null, null, null);
if (cursor.moveToFirst()) {
final int id = cursor.getInt(0);
if (DEBUG)
Log.d(TAG, "Got thumb ID: " + id);
if (mimeType.contains("video")) {
bm = MediaStore.Video.Thumbnails.getThumbnail(
resolver,
id,
MediaStore.Video.Thumbnails.MINI_KIND,
null);
} else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
bm = MediaStore.Images.Thumbnails.getThumbnail(
resolver,
id,
MediaStore.Images.Thumbnails.MINI_KIND,
null);
}
}
} catch (Exception e) {
if (DEBUG)
Log.e(TAG, "getThumbnail", e);
} finally {
if (cursor != null)
cursor.close();
}
}
return bm;
}
/**
* Get the Intent for selecting content to be used in an Intent Chooser.
*
* @return The intent for opening a file with Intent.createChooser()
* @author paulburke
*/
public static Intent createGetContentIntent() {
// Implicitly allow the user to select a particular kind of data
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// The MIME data type filter
intent.setType("*/*");
// Only return URIs that can be opened with ContentResolver
intent.addCategory(Intent.CATEGORY_OPENABLE);
return intent;
}
}

View File

@ -0,0 +1,47 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
public class JavaScriptInterface implements JavascriptCallback {
Context context;
MediNETActivity activity;
public JavaScriptInterface(MediNETActivity mediNETActivity,
Context applicationContext) {
context = applicationContext;
activity = mediNETActivity;
}
@JavascriptInterface
public void askToSignIn() {
MeditationAssistant ma = (MeditationAssistant) this.activity
.getApplication();
this.activity.finish();
ma.getMediNET().askToSignIn();
}
@JavascriptInterface
public void setKey(String key, String provider) {
Log.d("MeditationAssistant", "Setting key" + key);
MeditationAssistant ma = (MeditationAssistant) this.activity
.getApplication();
ma.setMediNETKey(key, provider);
ma.getMediNET().provider = provider;
ma.getMediNET().connect();
/*
* Bundle bundle = new Bundle(); bundle.putString("action",
* "changekey"); Intent mIntent = new Intent();
* mIntent.putExtras(bundle);
* this.activity.setResult(this.activity.RESULT_OK, mIntent);
*/
this.activity.finish();
}
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
}
}

View File

@ -0,0 +1,5 @@
package sh.ftp.rocketninelabs.meditationassistant;
public interface JavascriptCallback {
}

View File

@ -0,0 +1,309 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetFileDescriptor;
import android.content.res.TypedArray;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.util.Log;
import java.io.IOException;
public class ListPreferenceSound extends ListPreference {
private int mClickedDialogEntryIndex;
private CharSequence[] mEntries;
private CharSequence[] mEntryValues;
private CharSequence mSummary;
private String mValue;
private MediaPlayer mMediaPlayer = null;
private Context ctx = null;
public ListPreferenceSound(Context context) {
this(context, null);
}
public ListPreferenceSound(Context context, AttributeSet attrs) {
super(context, attrs);
ctx = context;
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
}
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ListPreference, 0, 0);
// mEntries = a.getTextArray(R.styleable.ListPreference_entries);
// mEntryValues = a.getTextArray(R.styleable.ListPreference_entryValues);
setEntries(a.getTextArray(R.styleable.ListPreference_entries));
setEntryValues(a.getTextArray(R.styleable.ListPreference_entryValues));
a.recycle();
mSummary = super.getSummary();
}
public int findIndexOfValue(String value) {
if (value != null && mEntryValues != null) {
for (int i = mEntryValues.length - 1; i >= 0; i--) {
if (mEntryValues[i].equals(value)) {
return i;
}
}
}
return -1;
}
public CharSequence[] getEntries() {
return mEntries;
}
public void setEntries(int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
public void setEntries(CharSequence[] entries) {
mEntries = entries;
}
public CharSequence getEntry() {
int index = getValueIndex();
return index >= 0 && mEntries != null ? mEntries[index] : null;
}
public CharSequence[] getEntryValues() {
return mEntryValues;
}
public void setEntryValues(int entryValuesResId) {
setEntryValues(getContext().getResources().getTextArray(
entryValuesResId));
}
public void setEntryValues(CharSequence[] entryValues) {
mEntryValues = entryValues;
}
@Override
public CharSequence getSummary() {
final CharSequence entry = getEntry();
if (mSummary == null || entry == null) {
return super.getSummary();
} else {
//Log.d("MeditationAssistant", "getsummary(): " + String.valueOf(mSummary) + " " + String.valueOf(entry));
try {
return String.format(mSummary.toString(), entry);
} catch (Exception e) {
e.printStackTrace();
return mSummary.toString();
}
}
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
if (summary == null && mSummary != null) {
mSummary = null;
} else if (summary != null && !summary.equals(mSummary)) {
mSummary = summary;
}
}
public String getValue() {
return mValue;
}
public void setValue(String value) {
mValue = value;
persistString(value);
}
private int getValueIndex() {
return findIndexOfValue(mValue);
}
public void setValueIndex(int index) {
if (mEntryValues != null) {
setValue(mEntryValues[index].toString());
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (mMediaPlayer != null) {
try {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.reset();
}
} catch (Exception e) {
Log.d("MeditationAssistant", "Got exception while stopping and resetting sound in ListPreferenceSound");
e.printStackTrace();
}
}
if (positiveResult && mClickedDialogEntryIndex >= 0
&& mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
setValue(value);
}
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = getValueIndex();
builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
String itemSelected = mEntryValues[mClickedDialogEntryIndex]
.toString();
Log.d("MeditationAssistant",
"Selected: " + String.valueOf(which) + " - "
+ itemSelected
);
if (itemSelected.equals("custom")) {
ListPreferenceSound.this.onClick(dialog,
DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
} else if (!itemSelected.equals("none")) {
if (mMediaPlayer != null) {
try {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.reset();
}
} catch (Exception e) {
Log.d("MeditationAssistant", "Got exception while stopping and resetting sound in ListPreferenceSound");
e.printStackTrace();
}
}
AssetFileDescriptor afd = ctx
.getResources()
.openRawResourceFd(
MeditationSounds
.getMeditationSound(itemSelected)
);
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(
afd.getFileDescriptor(),
afd.getStartOffset(),
afd.getDeclaredLength());
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.prepareAsync();
// mMediaPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (mMediaPlayer != null) {
mMediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(
MediaPlayer mp) {
mp.release();
}
});
mMediaPlayer
.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(
MediaPlayer mp) {
mp.start();
}
});
}
}
}
}
);
builder.setPositiveButton(
builder.getContext().getString(R.string.set),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("MeditationAssistant", "Set clicked");
ListPreferenceSound.this.onClick(dialog,
DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
}
}
);
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
setValue(myState.value);
}
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
return superState;
}
final SavedState myState = new SavedState(superState);
myState.value = getValue();
return myState;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
mValue = restoreValue ? getPersistedString(mValue)
: (String) defaultValue;
}
private static class SavedState extends BaseSavedState {
String value;
public SavedState(Parcel source) {
super(source);
value = source.readString();
}
public SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(value);
}
}
}

View File

@ -0,0 +1,417 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* Created by root on 11/2/13.
*/
public class MediNET {
public static Integer version = 5;
public String status = "disconnected";
public String result = "";
public MainActivity activity;
public MeditationSession session = new MeditationSession();
public String provider = "";
public ArrayList<MeditationSession> result_sessions = null;
public String announcement = "";
private Boolean debug = false;
private MeditationAssistant ma = null;
private MediNETTask task = null;
private Handler handler = new Handler();
private Runnable runnable;
private Runnable runnable2;
private Boolean runnable_finished = true;
private AlertDialog alertDialog = null;
private String browsetopage = "";
public MediNET(MainActivity _activity) {
activity = _activity;
runnable = new Runnable() {
@Override
public void run() {
handler.removeCallbacks(this);
getMeditationAssistant().updateWidgets();
runnable_finished = true;
}
};
runnable2 = new Runnable() {
@Override
public void run() {
handler.removeCallbacks(this);
Log.d("MeditationAssistant", "Delayed update() running...");
getMeditationAssistant().getMediNET().updated();
}
};
}
public static String durationToTimerString(long duration, boolean countDown) {
int hours = (int) duration / 3600;
int minutes = ((int) duration % 3600) / 60;
if (countDown) {
minutes += 1;
}
return String.valueOf(hours) + ":" + String.format("%02d", minutes);
}
public void askToSignIn() {
/*if (activity == null || activity.stopped) {
Log.d("MeditationAssistant",
"MainActivity null or stopped, restarting... Stopped: "
+ activity.stopped.toString());*/
if (activity == null) {
Intent openActivity = new Intent(getMeditationAssistant()
.getApplicationContext(), MainActivity.class);
openActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
openActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d("MeditationAssistant",
"Open MainActivity runnable is now running...");
askToSignIn();
}
}, 400);
getMeditationAssistant().getApplicationContext().startActivity(
openActivity);
return;
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (activity == null) {
Log.d("MeditationAssistant",
"askToSignIn activity is null, returning...");
return;
}
getMeditationAssistant().showSignInDialog(activity);
}
});
}
public void browseTo(MainActivity act, String page) {
activity = act;
browsetopage = page;
if (status.equals("success") || page.equals("community")) {
act.runOnUiThread(new Runnable() {
@Override
public void run() {
Intent openActivity = new Intent(activity
.getApplicationContext(), MediNETActivity.class);
openActivity.putExtra("page", browsetopage);
openActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
openActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
getMeditationAssistant().getApplicationContext()
.startActivity(openActivity);
}
});
} else {
askToSignIn();
}
}
public void resetSession() {
session = new MeditationSession();
}
public boolean connect() {
ConnectivityManager cm = (ConnectivityManager) getMeditationAssistant()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
Boolean internetconnected = (netInfo != null && netInfo.isConnectedOrConnecting());
if (!internetconnected) {
Log.d("MeditationAssistant",
"Cancelled MediNET connection: Internet isn't connected");
return false;
}
if (getMeditationAssistant().getMediNETKey().equals("")) {
askToSignIn();
return false;
}
runnable_finished = true;
if (!this.status.equals("success")) {
JSONObject jobj = new JSONObject();
try {
Log.d("MeditationAssistant", "Begin connect");
jobj.put("x", getMeditationAssistant().getMediNETKey());
} catch (JSONException e1) {
e1.printStackTrace();
}
// display json object being sent
// Log.d("MeditationAssistant", "JSON object send: " +
// jobj.toString());
status = "connecting";
updated();
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "connect";
task.context = activity.getApplicationContext();
Log.d("MeditationAssistant", "Executing MediNET Task");
task.doIt(this);
return true;
}
updated();
return false;
}
public Boolean deleteSessionByStarted(long started) {
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "deletesession";
task.actionextra = String.valueOf(started);
task.context = activity.getApplicationContext();
if (debug) {
task.nextURL += "&debug77";
}
task.doIt(this);
return true;
}
public void signInWithAuthToken(String authtoken) {
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "signin";
task.actionextra = authtoken;
task.context = activity.getApplicationContext();
task.doIt(this);
}
public MainActivity getActivity() {
return activity;
}
public void setActivity(MainActivity activity) {
this.activity = activity;
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.activity.getApplication();
}
return ma;
}
public MeditationSession getSession() {
return session;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Boolean postSession() {
return postSession(false, null);
}
public Boolean postSession(Boolean manualposting, FragmentActivity act) {
Log.d("MeditationAssistant", "Session.toString(): "
+ this.getSession().export().toString());
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.fragment_activity = act;
task.action = "postsession";
if (manualposting) {
task.actionextra = "manualposting";
} else {
// Only add streak if there isn't already a session for today
if (getMeditationAssistant().db.numSessionsByDate(getMeditationAssistant().db.timestampToAPIDate(getSession().completed * 1000)) == 0) {
getMeditationAssistant().addMeditationStreak();
if (getSession().streakday == 0) {
getSession().streakday = getMeditationAssistant().getMeditationStreak();
}
}
}
task.context = activity.getApplicationContext();
if (debug) {
task.nextURL += "&debug77";
}
task.doIt(this);
return true;
}
public void saveSession(Boolean manualposting, Boolean posted) {
Long postedlong = (long) 0;
if (posted) {
postedlong = (long) 1;
}
// Only add streak if there isn't already a session for that day
if (getMeditationAssistant().db.numSessionsByDate(getMeditationAssistant().db.timestampToAPIDate(getSession().completed * 1000)) == 0) {
if (!manualposting) {
getMeditationAssistant().addMeditationStreak();
if (getSession().streakday == 0) {
getSession().streakday = getMeditationAssistant().getMeditationStreak();
}
} else {
Calendar c_midnight = new GregorianCalendar();
c_midnight.setTime(new Date());
c_midnight.set(Calendar.HOUR_OF_DAY, 0);
c_midnight.set(Calendar.MINUTE, 0);
c_midnight.set(Calendar.SECOND, 0);
c_midnight.set(Calendar.MILLISECOND, 0);
if ((c_midnight.getTimeInMillis() / 1000) < getSession().started && (getSession().started - (c_midnight.getTimeInMillis() / 1000)) < 86400) { // After midnight today
getMeditationAssistant().addMeditationStreak();
if (getSession().streakday == 0) {
getSession().streakday = getMeditationAssistant().getMeditationStreak();
}
} else {
c_midnight.add(Calendar.DATE, -1);
if ((c_midnight.getTimeInMillis() / 1000) < getSession().started) { // After midnight yesterday
getMeditationAssistant().addMeditationStreak(false);
if (getSession().streakday == 0) {
getSession().streakday = getMeditationAssistant().getMeditationStreak();
}
}
}
}
}
getMeditationAssistant().db.addSession(new SessionSQL(
getSession().started, getSession().completed, getSession().length,
getSession().message, postedlong, getSession().streakday));
resetSession();
if (!manualposting) {
getMeditationAssistant().asktorate = true;
}
}
public void selectProvider(View v) {
ImageButton img = (ImageButton) v;
Intent intent = new Intent(getMeditationAssistant()
.getApplicationContext(), MediNETActivity.class);
if (img.getId() == R.id.btnGoogle) {
intent.putExtra("provider", "Google");
} else if (img.getId() == R.id.btnFacebook) {
intent.putExtra("provider", "Facebook");
} else if (img.getId() == R.id.btnAOL) {
intent.putExtra("provider", "AOL");
} else if (img.getId() == R.id.btnTwitter) {
intent.putExtra("provider", "Twitter");
} else if (img.getId() == R.id.btnLive) {
intent.putExtra("provider", "Live");
} else if (img.getId() == R.id.btnOpenID) {
intent.putExtra("provider", "OpenID");
}
getMeditationAssistant().getApplicationContext().startActivity(intent);
}
public void signOut() {
Log.d("MeditationAssistant", "Signing out");
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "signout";
task.context = activity.getApplicationContext();
if (debug) {
task.nextURL += "&debug77";
}
task.doIt(this);
status = "stopped";
getMeditationAssistant().setMediNETKey("", "");
if (!getMeditationAssistant().getPrefs().getBoolean("pref_autosignin", false)) {
getMeditationAssistant().getPrefs().edit().putString("key", "").apply();
}
//getMeditationAssistant().setMeditationStreak(0, 0);
updated();
}
public Boolean syncSessions() {
getMeditationAssistant().shortToast(getMeditationAssistant().getString(R.string.downloadingSessions));
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "syncsessions";
task.context = activity.getApplicationContext();
if (debug) {
task.nextURL += "&debug77";
}
task.doIt(this);
return true;
}
public Boolean uploadSessions() {
getMeditationAssistant().shortToast(getMeditationAssistant().getString(R.string.uploadingSessions));
if (task != null) {
task.cancel(true);
}
task = new MediNETTask();
task.action = "uploadsessions";
task.context = activity.getApplicationContext();
if (debug) {
task.nextURL += "&debug77";
}
task.doIt(this);
return true;
}
public void updateAfterDelay() {
Log.d("MeditationAssistant", "Update after delay: " + status);
handler.postDelayed(runnable2, 1750);
}
public void updated() {
Log.d("MeditationAssistant", "updated() " + status);
activity.updateTextsAsync();
if (runnable_finished) {
runnable_finished = false;
handler.postDelayed(runnable, 750);
}
}
}

View File

@ -0,0 +1,566 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.MailTo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.analytics.GoogleAnalytics;
import org.apache.http.cookie.Cookie;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
public class MediNETActivity extends Activity {
final Activity activity = this;
protected FrameLayout webViewPlaceholder = null;
protected WebView webView = null;
private AdView av = null;
private String provider = "";
private MeditationAssistant ma = null;
private Handler handler = new Handler();
private boolean signing_in = false;
private boolean hide_refresh = false;
public static Intent newEmailIntent(Context context, String address, String subject, String body, String cc) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{address});
intent.putExtra(Intent.EXTRA_TEXT, body);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_CC, cc);
intent.setType("message/rfc822");
return intent;
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.getApplication();
}
return ma;
}
public String getPageUrl(String page) {
TimeZone tz = TimeZone.getDefault();
Date now = new Date();
return "http://medinet.ftp.sh/client_android.php?v="
+ MediNET.version.toString() + "&avn="
+ String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&page=" + page + "&th="
+ ma.getMAThemeString() + "&tz="
+ String.valueOf(tz.getOffset(now.getTime())) + "&x="
+ getMeditationAssistant().getMediNETKey();
}
public void goTo(String go_to) {
String url;
if (go_to.equals("Google") || go_to.equals("Facebook")
|| go_to.equals("Twitter") || go_to.equals("AOL")
|| go_to.equals("OpenID") || go_to.equals("Live")
|| go_to.equals("LinkedIn")) {
setTitle(String.format(getString(R.string.signInWithProvider),
go_to));
url = "http://medinet.ftp.sh/client_android_login.php?v="
+ MediNET.version.toString() + "&avn="
+ String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&provider=" + go_to;
provider = go_to;
signing_in = true;
} else if (go_to.equals("gpl") || go_to.equals("lgpl")) {
setTitle("");
signing_in = true;
hide_refresh = true;
if (go_to.equals("gpl")) {
url = "file:///android_asset/gpl.html";
} else {
url = "file:///android_asset/lgpl.html";
}
} else {
if (go_to.equals("community")) {
setTitle(getString(R.string.community));
} else if (go_to.equals("sessions")) {
setTitle(getString(R.string.sessions));
} else if (go_to.equals("account")) {
setTitle(getString(R.string.account));
} else if (go_to.equals("forum")) {
setTitle(getString(R.string.forum));
} else if (go_to.equals("groups")) {
setTitle(getString(R.string.groups));
} else if (go_to.equals("signout")) {
} else {
return;
}
url = getPageUrl(go_to);
signing_in = false;
}
Log.d("MeditationAssistant", go_to + " - Going to: " + url);
webView.loadUrl(url);
setWindowBackground();
}
@SuppressLint({"AddJavascriptInterface", "SetJavaScriptEnabled"})
protected void initUI(Boolean activityOnCreate) {
webViewPlaceholder = ((FrameLayout) findViewById(R.id.webViewPlaceholder));
if (webView == null) {
webView = new WebView(getApplicationContext());
// potential fixes for keeping zoom
// webView.getSettings().setLoadWithOverviewMode(true);
// webView.getSettings().setUseWideViewPort(true);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int progress) {
if (Build.VERSION.SDK_INT >= 15) { // setProgress added API-15
activity.setProgress(progress * 100);
}
}
});
webView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
WebView.HitTestResult result = webView.getHitTestResult();
Log.d("MeditationAssistant", "Hit test");
if (result != null) {
if (result.getType() == WebView.HitTestResult.IMAGE_TYPE
|| result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
Log.d("MeditationAssistant",
"Image: " + result.toString());
Intent browserIntent = new Intent(
Intent.ACTION_VIEW, Uri.parse(result
.getExtra())
);
startActivity(browserIntent);
return true;
} else if (result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
Log.d("MeditationAssistant",
"Anchor: " + result.toString());
Intent browserIntent = new Intent(
Intent.ACTION_VIEW, Uri.parse(result
.getExtra())
);
startActivity(browserIntent);
return true;
}
}
return false;
}
});
webView.setHapticFeedbackEnabled(true);
webView.setLongClickable(true);
// webView.setInitialScale(getMeditationAssistant().getWebViewScale());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
webView.setLayoutParams(params);
webView.getSettings().setSupportZoom(true);
// webView.getSettings().setBuiltInZoomControls(true);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setScrollbarFadingEnabled(true);
webView.getSettings().setLoadsImagesAutomatically(true);
if (Build.VERSION.SDK_INT < 11) {
webView.getSettings();
webView.setBackgroundColor(Color.TRANSPARENT);
} else {
// Fix background flicker
webView.getSettings();
webView.setBackgroundColor(Color.argb(1, 0, 0, 0));
}
// JavaScript
webView.addJavascriptInterface(
new JavaScriptInterface(this, this.getApplicationContext()),
"MA");
webView.getSettings().setJavaScriptEnabled(true);
// Cookies
List<Cookie> cookies = getMeditationAssistant().getHttpClient()
.getCookieStore().getCookies();
if (!cookies.isEmpty()) {
CookieManager cookieManager = CookieManager.getInstance();
for (Cookie cookie : cookies) {
String cookieString = cookie.getName() + "="
+ cookie.getValue() + "; domain="
+ cookie.getDomain();
cookieManager.setCookie("medinet.ftp.sh", cookieString);
CookieSyncManager.getInstance().sync();
}
}
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
if (Uri.parse(url) != null && Uri.parse(url).getHost() != null && Uri.parse(url).getHost().equals("medinet.ftp.sh")) {
if (webView.getTitle() != null
&& !webView.getTitle().trim().equals("")) {
setTitle(webView.getTitle());
}
signing_in = url.contains("/hybridauth/");
} else {
/*
* setTitle(String.format(getString(R.string.
* signInWithProvider), provider));
*/
}
setWindowBackground();
// view.setInitialScale(getMeditationAssistant().getWebViewScale());
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
/*getMeditationAssistant().setWebViewScale(
(int) (100 * view.getScale()));*/
Log.d("MeditationAssistant",
"Signing_in: " + String.valueOf(signing_in) + " - "
+ url
);
if (url != null && url.startsWith("mailto:")) {
MailTo mt = MailTo.parse(url);
Intent i = newEmailIntent(MediNETActivity.this, mt.getTo(), mt.getSubject(), mt.getBody(), mt.getCc());
startActivity(i);
view.reload();
return true;
/*} else if (url != null && Uri.parse(url) != null && Uri.parse(url).getHost() != null
&& !Uri.parse(url).getHost()
.equals("medinet.ftp.sh")
&& webView.getUrl() != null
&& Uri.parse(webView.getUrl()).getHost() != null && Uri.parse(webView.getUrl()).getHost()
.equals("medinet.ftp.sh")
&& !webView.getUrl().contains("provider=OpenID")) {
Log.d("MA", "!!!!!!!!!!!!!!!!! OPENING!!!");
Intent browserIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse(url));
startActivity(browserIntent);*/
} else {
view.loadUrl(url);
}
Log.d("MA", Uri.parse(url).toString());
Log.d("MA", Uri.parse(url).getHost());
return true;
}
});
webView.getSettings().setSupportMultipleWindows(true);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, android.os.Message resultMsg) {
WebView.HitTestResult result = view.getHitTestResult();
String data = result.getExtra();
Context context = view.getContext();
context.startActivity(new Intent(
Intent.ACTION_VIEW,
Uri.parse(data)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
return false;
}
});
}
// webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
webViewPlaceholder.addView(webView);
// webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
if (activityOnCreate) {
if (getIntent().hasExtra("provider")) {
provider = getIntent().getStringExtra("provider");
if (provider.equals("Google") || provider.equals("Facebook")
|| provider.equals("Twitter") || provider.equals("AOL")
|| provider.equals("OpenID") || provider.equals("Live")
|| provider.equals("LinkedIn")) {
signing_in = true;
goTo(provider);
}
} else if (getIntent().hasExtra("page")
&& (getIntent().getStringExtra("page").equals("community")
|| getIntent().getStringExtra("page").equals(
"sessions")
|| getIntent().getStringExtra("page").equals(
"account")
|| getIntent().getStringExtra("page").equals(
"groups")
|| getIntent().getStringExtra("page").equals(
"forum")
|| getIntent().getStringExtra("page").equals("gpl") || getIntent()
.getStringExtra("page").equals("lgpl"))) {
signing_in = false;
goTo(getIntent().getStringExtra("page"));
}
} else {
if (getPackageName().equals(
"sh.ftp.rocketninelabs.meditationassistant")) {
Log.d("MeditationAssistant", "Fetching ad");
// AdView av = new AdView(this, AdSize.SMART_BANNER,
// "a15110a172d3cff");
av = (AdView) findViewById(R.id.adViewMediNET);
av.setVisibility(View.VISIBLE);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
av.loadAd(adRequest);
/*
* (new Thread() { public void run() { Looper.prepare(); AdView
* av = (AdView) findViewById(R.id.adViewMediNET);
*
*
*
* av.loadAd(adrequest); } }).start();
*/
} else {
// av.setVisibility(View.GONE);
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (webView != null) {
webViewPlaceholder.removeView(webView);
}
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_medinet);
initUI(false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_PROGRESS);
super.onCreate(savedInstanceState);
setTheme(getMeditationAssistant().getMATheme());
setContentView(R.layout.activity_medinet);
getActionBar().setDisplayHomeAsUpEnabled(true);
if (getPackageName()
.equals("sh.ftp.rocketninelabs.meditationassistant")) {
Log.d("MeditationAssistant", "Fetching ad");
// AdView av = new AdView(this, AdSize.SMART_BANNER,
// "a15110a172d3cff");
av = (AdView) findViewById(R.id.adViewMediNET);
av.setVisibility(View.VISIBLE);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
av.loadAd(adRequest);
}
if (getMeditationAssistant().sendUsageReports()) {
getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER);
}
initUI(true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.medinet, menu);
return true;
}
@Override
public void onDestroy() {
if (getMeditationAssistant().getMediNET() != null) {
if (getMeditationAssistant().getMediNET().getStatus() != null
&& getMeditationAssistant().getMediNET().getStatus()
.equals("connecting")) {
getMeditationAssistant().getMediNET().setStatus("disconnected");
}
getMeditationAssistant().getMediNET().updated();
}
if (av != null) {
av.destroy();
}
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("MeditationAssistant",
"Selected menu item: " + String.valueOf(item.getItemId()));
int itemId = item.getItemId();
if (itemId == android.R.id.home) {
finish();
return true;
} else if (itemId == R.id.refreshMediNET) {
webView.loadUrl("javascript:window.location.reload(true)");
return true;
} else if (itemId == R.id.menuMediNETCommunity) {
goTo("community");
return true;
} else if (itemId == R.id.menuMediNETSessions) {
goTo("sessions");
return true;
} else if (itemId == R.id.menuMediNETForum) {
goTo("forum");
return true;
} else if (itemId == R.id.menuMediNETGroups) {
goTo("groups");
return true;
} else if (itemId == R.id.menuMediNETAccount) {
goTo("account");
return true;
} else if (itemId == R.id.menuMediNETBack) {
if (webView.canGoBack()) {
webView.goBack();
}
return true;
} else if (itemId == R.id.menuMediNETForward) {
if (webView.canGoForward()) {
webView.goForward();
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPause() {
if (av != null) {
av.pause();
}
CookieSyncManager.getInstance().stopSync();
super.onStop();
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (signing_in) {
menu.findItem(R.id.menuMediNET).setVisible(false);
} else {
menu.findItem(R.id.menuMediNET).setVisible(true);
}
if (hide_refresh) {
menu.findItem(R.id.refreshMediNET).setVisible(false);
} else {
menu.findItem(R.id.refreshMediNET).setVisible(true);
}
super.onPrepareOptionsMenu(menu);
return true;
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
webView.restoreState(savedInstanceState);
}
@Override
protected void onResume() {
CookieSyncManager.getInstance().startSync();
super.onResume();
if (av != null) {
av.resume();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
webView.saveState(outState);
}
@Override
public void onStart() {
super.onStart();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}
public void setWindowBackground() {
if (getMeditationAssistant().getMATheme() != R.style.MeditationDarkTheme && getMeditationAssistant().getMATheme() != R.style.Buddhism) {
getWindow().setBackgroundDrawable(
getResources().getDrawable(
android.R.drawable.screen_background_light)
);
} else {
/*getWindow()
.setBackgroundDrawable(
getResources().getDrawable(
android.R.drawable.background_holo_dark));*/
webView.getSettings();
if (signing_in) {
webView.setBackgroundColor(Color.WHITE);
} else {
if (Build.VERSION.SDK_INT < 11) {
webView.setBackgroundColor(Color.TRANSPARENT);
} else {
// Fix background flicker
webView.setBackgroundColor(Color.argb(1, 0, 0, 0));
}
}
}
}
}

View File

@ -0,0 +1,479 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
public class MediNETTask extends AsyncTask<MediNET, Integer, MediNET> {
public Context context;
public String nextURL = null;
public String action = "";
public String actionextra = "";
public MediNET medinet;
public String x;
public FragmentActivity fragment_activity = null;
private BufferedReader webReader;
private MeditationAssistant ma = null;
private Crypt crypt = new Crypt();
@Override
protected MediNET doInBackground(MediNET... medinets) {
this.medinet = medinets[0];
this.medinet.result = "";
if (isCancelled()) {
Log.d("MeditationAssistant", "Task cancelled");
return this.medinet;
}
TimeZone tz = TimeZone.getDefault();
Date now = new Date();
int offsetFromUTC = tz.getOffset(now.getTime());
String appVersion = getMeditationAssistant().getMAAppVersion() + (getMeditationAssistant().getMAIsAppFull() ? "full" : "free");
if (this.nextURL == null) {
this.nextURL = "http://medinet.ftp.sh/client_android.php?v="
+ MediNET.version.toString() + "&av="
+ appVersion + "&avn="
+ String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&tz="
+ String.valueOf(offsetFromUTC);
}
if (action.equals("signin")) {
this.nextURL = "http://medinet.ftp.sh/client_android_login_oauth2.php?v="
+ MediNET.version.toString() + "&av="
+ appVersion + "&avn="
+ String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&tz="
+ String.valueOf(offsetFromUTC) + "&token=" + actionextra;
}
Log.d("MeditationAssistant", "URL => " + this.nextURL);
HttpPost httpPost = new HttpPost(this.nextURL);
HttpResponse webResponse = null;
ArrayList<SessionSQL> sessionssql = null;
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("x", medinet
.getMeditationAssistant().getMediNETKey()));
if (action.equals("connect")) {
nameValuePairs.add(new BasicNameValuePair("action", "connect"));
} else if (action.equals("postsession")) {
nameValuePairs.add(new BasicNameValuePair("postsession", Crypt
.bytesToHex(crypt.encrypt(medinet.getSession().export()
.toString()))));
if (actionextra.equals("manualposting")) {
nameValuePairs.add(new BasicNameValuePair("manualposting",
"true"));
}
} else if (action.equals("deletesession")) {
nameValuePairs.add(new BasicNameValuePair("action",
"deletesession")); // Session start time
nameValuePairs.add(new BasicNameValuePair("session",
actionextra));
} else if (action.equals("syncsessions")) {
nameValuePairs.add(new BasicNameValuePair("action",
"syncsessions"));
} else if (action.equals("uploadsessions")) {
JSONArray jsonsessions = new JSONArray();
sessionssql = getMeditationAssistant().db.getAllLocalSessions();
if (sessionssql.size() == 0) {
getMeditationAssistant().longToast(
medinet.activity,
getMeditationAssistant().getString(R.string.sessionsNotImported));
return medinet;
}
for (SessionSQL uploadsessionsql : sessionssql) {
MeditationSession uploadsession = new MeditationSession();
uploadsession.id = uploadsessionsql._id;
uploadsession.length = uploadsessionsql._length;
uploadsession.started = uploadsessionsql._started;
uploadsession.completed = uploadsessionsql._completed;
uploadsession.streakday = uploadsessionsql._streakday;
uploadsession.message = uploadsessionsql._message;
jsonsessions.put(uploadsession.export());
}
Log.d("MeditationAssistant", jsonsessions.toString());
nameValuePairs.add(new BasicNameValuePair("uploadsessions", Crypt
.bytesToHex(crypt.encrypt(jsonsessions.toString()))));
} else if (action.equals("signout")) {
nameValuePairs
.add(new BasicNameValuePair("signout", "signout"));
}
Log.d("MeditationAssistant", "Post to " + this.nextURL + ", "
+ nameValuePairs.toString());
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
webResponse = getMeditationAssistant().getHttpClient().execute(
httpPost, getMeditationAssistant().getHttpContext());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
getMeditationAssistant().longToast(getMeditationAssistant().getString(R.string.sessionNotPosted));
e.printStackTrace();
}
if (webResponse == null) {
Log.d("MeditationAssistant", "Unable to connect to MediNET");
medinet.status = "disconnected";
if (!getMeditationAssistant().getMediNETKey().equals("")
&& medinet.activity != null) {
getMeditationAssistant().longToast(medinet.activity,
getMeditationAssistant().getString(R.string.unableToConnect));
medinet.activity.updateTextsAsync();
}
return medinet;
}
String result = "";
try {
this.webReader = new BufferedReader(new InputStreamReader(
webResponse.getEntity().getContent()));
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String line;
try {
while ((line = this.webReader.readLine()) != null) {
result += line + "\n";
}
} catch (IOException e) {
e.printStackTrace();
}
Calendar date = new GregorianCalendar();
date.setTimeZone(TimeZone.getDefault());
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
date.add(Calendar.DAY_OF_MONTH, 2);
Log.d("MeditationAssistant",
"two days: " + date.getTimeZone().getDisplayName()
+ String.valueOf(date.getTimeInMillis() / 1000)
);
Log.d("MeditationAssistant", "Result: " + result);
if (webResponse.getFirstHeader("x-MediNET") != null) {
if (webResponse.getFirstHeader("x-MediNET").getValue()
.equals("signin")) {
this.medinet.askToSignIn();
} else {
if (action.equals("signin") && webResponse.getFirstHeader("x-MediNET-Key") != null) {
/* Oauth2 sign in */
Log.d("MeditationAssistant", "Header key: "
+ webResponse.getFirstHeader("x-MediNET-Key")
.getValue());
if (!webResponse.getFirstHeader("x-MediNET-Key")
.getValue().equals("")) {
getMeditationAssistant().setMediNETKey(webResponse.getFirstHeader("x-MediNET-Key")
.getValue(), "Google");
//getMeditationAssistant().getMediNET().connect();
try {
getMeditationAssistant().shortToast(
medinet.activity,
getMeditationAssistant().getString(R.string.mediNETConnected));
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (webResponse.getFirstHeader("x-MediNET-Streak") != null) {
Log.d("MeditationAssistant", "Header streak: "
+ webResponse.getFirstHeader("x-MediNET-Streak")
.getValue());
if (!webResponse.getFirstHeader("x-MediNET-Streak")
.getValue().equals("")) {
String streak_header = webResponse.getFirstHeader(
"x-MediNET-Streak").getValue();
if (streak_header.contains(",")) {
getMeditationAssistant().setMeditationStreak(Integer.valueOf(streak_header.split(",")[0]), Integer.valueOf(streak_header.split(",")[1]));
getMeditationAssistant().recalculateMeditationStreak();
}
}
}
if (webResponse.getFirstHeader("x-MediNET-Meditating") != null) {
if (!webResponse.getFirstHeader("x-MediNET-Meditating")
.getValue().equals("")) {
// TODO: Was this going to be a meditating-now feature?
}
}
if (webResponse.getFirstHeader("x-MediNET-MaxStreak") != null) {
if (!webResponse.getFirstHeader("x-MediNET-MaxStreak")
.getValue().equals("")) {
Integer maxstreak = Integer.valueOf(webResponse.getFirstHeader("x-MediNET-MaxStreak")
.getValue());
if (maxstreak > getMeditationAssistant().getLongestMeditationStreak()) {
getMeditationAssistant().setLongestMeditationStreak(maxstreak);
}
}
}
}
Log.d("MeditationAssistant", "Header: "
+ webResponse.getFirstHeader("x-MediNET").getValue());
if (!result.equals("")
&& !result.trim().startsWith("<")) {
JSONObject jsonObj;
try {
jsonObj = new JSONObject(result);
Log.d("MeditationAssistant",
"jsonobj: " + jsonObj.toString());
if (jsonObj.has("status")) {
medinet.status = jsonObj.getString("status");
}
if (jsonObj.has("result")) {
medinet.result = jsonObj.getString("result");
}
if (jsonObj.has("announce")) {
medinet.announcement = jsonObj.getString("announce");
try {
medinet.activity.runOnUiThread(new Runnable() {
@Override
public void run() {
getMeditationAssistant()
.showAnnouncementDialog(null);
}
});
} catch (Exception e) {
Log.d("MeditationAssistant",
"Caught error while parsing announcement...");
e.printStackTrace();
}
}
if (action.equals("connect")) {
if (!getMeditationAssistant().getPrefs().getBoolean(
"asked_staledata", false)) {
try {
medinet.activity.runOnUiThread(new Runnable() {
@Override
public void run() {
getMeditationAssistant()
.showStaleDataDialog();
}
});
} catch (Exception e) {
Log.d("MeditationAssistant",
"Caught error while showing stale data dialog...");
e.printStackTrace();
}
getMeditationAssistant().getPrefs().edit()
.putBoolean("asked_staledata", true)
.apply();
}
} else if (action.equals("postsession")) {
if (medinet.result.equals("posted")) {
if (actionextra.equals("manualposting")) {
if (fragment_activity != null) {
fragment_activity
.runOnUiThread(new Runnable() {
@Override
public void run() {
getMeditationAssistant()
.shortToast(
getMeditationAssistant().getString(R.string.sessionPosted));
}
});
}
} else {
medinet.saveSession(false, true);
}
} else if (medinet.result.equals("alreadyposted")
&& actionextra.equals("manualposting")
&& fragment_activity != null) {
fragment_activity.runOnUiThread(new Runnable() {
@Override
public void run() {
getMeditationAssistant().shortToast(
getMeditationAssistant().getString(R.string.sessionAlreadyPosted));
}
});
}
} else if (action.equals("deletesession")) {
if (medinet.result.equals("deleted")) {
Log.d("MeditationAssistant", "Deleted session");
getMeditationAssistant().shortToast(
medinet.activity,
getMeditationAssistant().getString(R.string.sessionDeletedMediNET));
SessionSQL deletedsession = getMeditationAssistant().db.getSessionByStarted(Long.valueOf(actionextra));
if (deletedsession != null) {
deletedsession._isposted = (long) 0;
try {
getMeditationAssistant().db.updateSession(deletedsession);
} catch (Exception e) {
// Do nothing, it was probably deleted locally as well
}
}
} else if (medinet.result.equals("notdeleted")) {
getMeditationAssistant().shortToast(
medinet.activity,
getMeditationAssistant().getString(R.string.sessionNotFoundMediNET));
} else if (medinet.result.equals("accessdenied")) {
getMeditationAssistant()
.shortToast(medinet.activity,
getMeditationAssistant().getString(R.string.sessionNotProperAccount));
}
} else if (action.equals("uploadsessions")) {
if (sessionssql != null && medinet.result.equals("uploaded")) {
for (SessionSQL sessionsql : sessionssql) {
sessionsql._isposted = (long) 1;
getMeditationAssistant().db.updateSession(sessionsql);
}
Integer sessuploaded = sessionssql.size();
getMeditationAssistant().longToast(
medinet.activity,
String.format(getMeditationAssistant().getResources().getQuantityString(
R.plurals.sessionsUploaded, sessuploaded,
sessuploaded), String.valueOf(sessuploaded))
);
} else {
getMeditationAssistant().longToast(
medinet.activity,
getMeditationAssistant().getString(R.string.sessionsNotImported));
}
} else if (action.equals("syncsessions")) {
JSONArray jArray = jsonObj.getJSONArray("syncsessions");
Integer sessimported = 0;
SessionSQL sess;
for (int i = 0; i < jArray.length(); i++) {
JSONObject session = jArray.getJSONObject(i);
if (getMeditationAssistant().db
.getSessionByStarted(session
.getLong("started")) == null) {
sessimported += 1;
sess = new SessionSQL();
sess._length = session.getLong("length");
sess._started = session.getLong("started");
sess._completed = session.getLong("completed"); // Added in API 5
sess._message = session.getString("message");
sess._streakday = session.getLong("streakday");
sess._isposted = (long) 1;
Log.d("MeditationAssistant",
"Adding session started at "
+ String.valueOf(sess._started)
);
getMeditationAssistant().db.addSession(sess);
} else {
Log.d("MeditationAssistant",
"Skipping session " + String.valueOf(session));
}
}
if (sessimported > 0) {
getMeditationAssistant().longToast(
medinet.activity,
String.format(getMeditationAssistant().getResources().getQuantityString(
R.plurals.sessionsImported, sessimported,
sessimported), String.valueOf(sessimported))
);
} else {
getMeditationAssistant().longToast(
medinet.activity,
getMeditationAssistant().getString(R.string.sessionsNotImported));
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
publishProgress();
medinet.updateAfterDelay();
if (context == null) {
Throwable t = new Throwable();
t.printStackTrace();
}
return medinet;
}
public void doIt(MediNET m) {
try {
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, m);
} catch (Exception e) {
execute(m);
e.printStackTrace();
}
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) medinet.activity.getApplication();
}
return ma;
}
@Override
protected void onPostExecute(MediNET medinet) {
Log.d("MeditationAssistant",
"onPostExecute: " + String.valueOf(action));
if (action != null) {
if (action.equals("connect")) {
try {
MainActivity mainActivity = medinet.activity;
mainActivity.updateTexts();
Log.d("MeditationAssistant",
"Updated texts from finished 'connect'");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
Log.d("MeditataionAssistant", "Progress update");
medinet.updated();
medinet.activity.updateTextsAsync();
}
}

View File

@ -0,0 +1,87 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MeditationProvider extends AppWidgetProvider {
private int[] mergeInts(int[] arg1, int[] arg2) {
int[] result = new int[arg1.length + arg2.length];
System.arraycopy(arg1, 0, result, 0, arg1.length);
System.arraycopy(arg2, 0, result, arg1.length, arg2.length);
return result;
}
@Override
public void onEnabled(Context context) {
Log.d("MeditationAssistant", "Widget onEnabled");
super.onEnabled(context);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent != null) {
Log.d("MeditationAssistant", "Provider intent: " + intent.toString());
}
if (intent != null
&& intent.getAction() != null
&& intent.getAction().equals(
AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
AppWidgetManager gm = AppWidgetManager.getInstance(context);
int[] ids = gm.getAppWidgetIds(new ComponentName(context,
MeditationProvider.class));
ids = mergeInts(ids, gm.getAppWidgetIds(new ComponentName(context,
MeditationProvider2.class)));
ids = mergeInts(ids, gm.getAppWidgetIds(new ComponentName(context,
MeditationProvider3.class)));
onUpdate(context, gm, ids);
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent intent = new Intent(context, MeditationService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
context.startService(intent);
String ids_formatted = "";
for (int id : appWidgetIds) {
ids_formatted += ", " + String.valueOf(id);
}
Log.d("MeditationAssistant", "Widget onUpdate, service started for IDs: " + ids_formatted);
super.onUpdate(context, appWidgetManager, appWidgetIds);
/*
* int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
* for (int widgetId : allWidgetIds) { RemoteViews remoteViews = new
* RemoteViews(context.getPackageName(), R.layout.widget_layout);
*
* SActivity ctx = (SActivity) context; Log.d("MeditationAssistant",
* "!!!" + ctx.getApplication().toString()); // Set the text
* remoteViews.setTextViewText(R.id.txtDays, ctx.getApplication()
* .toString());
*
* // Register an onClickListener // Intent intent = new Intent(context,
* MeditationProvider.class);
*
* // intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); //
* intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, //
* appWidgetIds);
*
* // PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
* // 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //
* remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
* appWidgetManager.updateAppWidget(widgetId, remoteViews); }
*/
}
}

View File

@ -0,0 +1,5 @@
package sh.ftp.rocketninelabs.meditationassistant;
public class MeditationProvider1 extends MeditationProvider {
}

View File

@ -0,0 +1,5 @@
package sh.ftp.rocketninelabs.meditationassistant;
public class MeditationProvider2 extends MeditationProvider {
}

View File

@ -0,0 +1,5 @@
package sh.ftp.rocketninelabs.meditationassistant;
public class MeditationProvider3 extends MeditationProvider {
}

View File

@ -0,0 +1,76 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;
public class MeditationService extends Service {
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
Log.d("MeditationAssistant", "Widget onStartCommand(): " + String.valueOf(intent));
if (intent == null) {
Log.d("MeditationAssistant", "Widget intent was null, exiting...");
return START_STICKY;
}
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
/*
* ComponentName thisWidget = new ComponentName(getApplicationContext(),
* MeditationProvider.class);
*/
for (int widgetId : allWidgetIds) {
RemoteViews updateViews = new RemoteViews(this.getPackageName(),
R.layout.widget_layout);
getApplication();
MeditationAssistant ma = (MeditationAssistant) this
.getApplication();
if (ma.getMeditationStreak() > 0) {
updateViews.setTextViewText(R.id.txtWidgetDays,
String.valueOf(ma.getMeditationStreak()));
updateViews.setTextViewText(
R.id.txtWidgetText,
getResources().getQuantityString(
R.plurals.daysOfMeditationWithoutCount,
ma.getMeditationStreak())
);
} else {
updateViews.setTextViewText(R.id.txtWidgetDays,
getString(R.string.ignore_om));
updateViews.setTextViewText(R.id.txtWidgetText,
getString(R.string.meditateToday));
}
Intent clickintent = new Intent(getApplicationContext(),
MainActivity.class);
// clickintent.putExtra("widgetid", startId);
clickintent.setAction("widgetclick");
PendingIntent pendingIntent = PendingIntent.getActivity(
getApplicationContext(), 0, clickintent, 0);
updateViews.setOnClickPendingIntent(R.id.layWidget, pendingIntent);
updateViews.setOnClickPendingIntent(R.id.txtWidgetDays,
pendingIntent);
updateViews.setOnClickPendingIntent(R.id.txtWidgetText,
pendingIntent);
appWidgetManager.updateAppWidget(widgetId, updateViews);
}
return START_STICKY;
}
}

View File

@ -0,0 +1,30 @@
package sh.ftp.rocketninelabs.meditationassistant;
import org.json.JSONException;
import org.json.JSONObject;
public class MeditationSession {
public long id = 0;
public long length = 0;
public long started = 0;
public long completed = 0;
public long streakday = 0;
public String date = "";
public String time = "";
public String message = "";
public JSONObject export() {
JSONObject jobj = new JSONObject();
try {
jobj.put("id", id);
jobj.put("length", length);
jobj.put("started", started);
jobj.put("completed", completed);
jobj.put("streakday", streakday);
jobj.put("message", message);
} catch (JSONException e1) {
e1.printStackTrace();
}
return jobj;
}
}

View File

@ -0,0 +1,45 @@
package sh.ftp.rocketninelabs.meditationassistant;
public class MeditationSounds {
public static int getMeditationSound(String sound) {
if (sound.equals("gong")) {
return R.raw.gong;
} else if (sound.equals("gong_burmese")) {
return R.raw.gong_burmese;
} else if (sound.equals("gong_metal")) {
return R.raw.gong_metal;
} else if (sound.equals("gong_heavy")) {
return R.raw.gong_heavy;
} else if (sound.equals("bell_indian")) {
return R.raw.bell_indian;
} else if (sound.equals("bell_temple")) {
return R.raw.bell_temple;
} else if (sound.equals("tinsha")) {
return R.raw.tinsha;
} else if (sound.equals("None")) {
return 0;
}
return R.raw.gong;
}
public static String getMeditationSoundName(String sound) { // TODO: Localize
if (sound.equals("gong")) {
return "Gong";
} else if (sound.equals("gong_burmese")) {
return "Burmese gong";
} else if (sound.equals("gong_metal")) {
return "Metal gong";
} else if (sound.equals("gong_heavy")) {
return "Heavy gong";
} else if (sound.equals("bell_indian")) {
return "Indian bell";
} else if (sound.equals("bell_temple")) {
return "Temple bell";
} else if (sound.equals("tinsha")) {
return "Three Tinsha";
} else if (sound.equals("none")) {
return "";
}
return "Gong";
}
}

View File

@ -0,0 +1,17 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
public class MonthAdapter extends MonthAdapterMA {
public MonthAdapter(Context c, int month, int year, DisplayMetrics metrics, ProgressActivity _pa,
MeditationAssistant _ma) {
super(c, month, year, metrics, _pa, _ma);
}
@Override
protected void onDate(int[] date, int position, View item) {
}
}

View File

@ -0,0 +1,303 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
public abstract class MonthAdapterMA extends BaseAdapter {
private final int[] mDaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30,
31, 30, 31};
private GregorianCalendar mCalendar;
private Calendar mCalendarToday;
private Context mContext;
private DisplayMetrics mDisplayMetrics;
private List<String> mItems;
private int mMonth;
private int mYear;
private int mDaysShown;
private int mDaysLastMonth;
private int mDaysNextMonth;
private int mDayHeight;
private String[] mDays = null;
private MeditationAssistant ma = null;
private ProgressActivity pa = null;
public MonthAdapterMA(Context c, int month, int year,
DisplayMetrics metrics, ProgressActivity _pa, MeditationAssistant _ma) {
mContext = c;
mDayHeight = MeditationAssistant.dpToPixels(50, mContext);
mMonth = month;
mYear = year;
mCalendar = new GregorianCalendar(mYear, mMonth, 1);
mCalendarToday = Calendar.getInstance();
mDisplayMetrics = metrics;
ma = _ma;
pa = _pa;
mDays = new String[]{mContext.getString(R.string.dayMondayShort),
mContext.getString(R.string.dayTuesdayShort),
mContext.getString(R.string.dayWednesdayShort),
mContext.getString(R.string.dayThursdayShort),
mContext.getString(R.string.dayFridayShort),
mContext.getString(R.string.daySaturdayShort),
mContext.getString(R.string.daySundayShort)};
populateMonth();
}
private int daysInMonth(int month) {
int daysInMonth = mDaysInMonth[month];
if (month == 1 && mCalendar.isLeapYear(mYear))
daysInMonth++;
return daysInMonth;
}
private int getBarHeight() {
switch (mDisplayMetrics.densityDpi) {
case DisplayMetrics.DENSITY_HIGH:
return 48;
case DisplayMetrics.DENSITY_MEDIUM:
return 32;
case DisplayMetrics.DENSITY_LOW:
return 24;
default:
return 48;
}
}
@Override
public int getCount() {
return mItems.size();
}
private int[] getDate(int position) {
int date[] = new int[3];
if (position <= 6) {
return null; // day names
} else if (position <= mDaysLastMonth + 6) {
// previous month
date[0] = Integer.parseInt(mItems.get(position));
if (mMonth == 0) {
date[1] = 11;
date[2] = mYear - 1;
} else {
date[1] = mMonth - 1;
date[2] = mYear;
}
} else if (position <= mDaysShown - mDaysNextMonth) {
// current month
date[0] = position - (mDaysLastMonth + 6);
date[1] = mMonth;
date[2] = mYear;
} else {
// next month
date[0] = Integer.parseInt(mItems.get(position));
if (mMonth == 11) {
date[1] = 0;
date[2] = mYear + 1;
} else {
date[1] = mMonth + 1;
date[2] = mYear;
}
}
return date;
}
private int getDay(int day) {
switch (day) {
case Calendar.MONDAY:
return 0;
case Calendar.TUESDAY:
return 1;
case Calendar.WEDNESDAY:
return 2;
case Calendar.THURSDAY:
return 3;
case Calendar.FRIDAY:
return 4;
case Calendar.SATURDAY:
return 5;
case Calendar.SUNDAY:
return 6;
default:
return 0;
}
}
@Override
public Object getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public MeditationAssistant getMeditationAssistant() {
return ma;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final TextView view = new TextView(mContext);
view.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
view.setText(mItems.get(position));
int[] date = getDate(position);
if (date != null) {
view.setTextSize(20);
String date_formatted = String.valueOf(date[0]) + "-"
+ String.valueOf(date[1] + 1) + "-"
+ String.valueOf(date[2]);
int numSessions = getMeditationAssistant().db.numSessionsByDate(date_formatted);
if (numSessions > 0) {
// At least one meditation session exists for this date
view.setTag(R.id.calendarDate, date);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int[] date = (int[]) view.getTag(R.id.calendarDate);
if (date != null) {
pa.goToSessionAtDate(date);
}
}
});
if (getMeditationAssistant().getMAThemeString().equals("dark")) {
/*int bgcolor = (date[1] == mMonth) ? R.color.highlighted_text_light
: R.color.dim_foreground_light;*/
int bgcolor = (date[1] == mMonth) ? android.R.color.holo_blue_dark
: android.R.color.secondary_text_dark;
// : android.R.color.dim_foreground_light;
view.setBackgroundColor(getMeditationAssistant()
.getResources().getColor(bgcolor));
} else {
int bgcolor = (date[1] == mMonth) ? R.color.highlighted_text_dark
: R.color.dim_foreground_dark;
//: R.color.dim_foreground_holo_dark;
view.setBackgroundColor(getMeditationAssistant()
.getResources().getColor(bgcolor));
}
if (numSessions > 1) { // Make large and bold if there's more than one session
view.setTypeface(null, Typeface.BOLD);
view.setTextSize(23);
}
}
view.setHeight(mDayHeight);
if (date[1] != mMonth) { // previous or next month
if (getMeditationAssistant().getMAThemeString().equals("dark")) {
view.setTextColor(getMeditationAssistant().getResources()
.getColor(android.R.color.tertiary_text_light));
} else {
view.setTextColor(getMeditationAssistant().getResources()
.getColor(android.R.color.tertiary_text_dark));
}
} else { // current month
view.setTextColor(getMeditationAssistant()
.getResources()
.getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant()
.getMATheme(),
new int[]{android.R.attr.textColorPrimary}
)
.getResourceId(0, 0)
));
if (isToday(date[0], date[1], date[2])) {
view.setPaintFlags(view.getPaintFlags()
| Paint.UNDERLINE_TEXT_FLAG);
}
}
} else {
view.setTextSize(16);
view.setPadding(0, 0, 0,
MeditationAssistant.dpToPixels(1, mContext));
view.setTypeface(null, Typeface.BOLD);
view.setTextColor(getMeditationAssistant().getResources().getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.textColorPrimary})
.getResourceId(0, 0)
));
view.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
}
onDate(date, position, view);
return view;
}
@Override
public boolean isEnabled(int position) {
return false;
}
private boolean isToday(int day, int month, int year) {
return mCalendarToday.get(Calendar.MONTH) == month
&& mCalendarToday.get(Calendar.YEAR) == year
&& mCalendarToday.get(Calendar.DAY_OF_MONTH) == day;
}
/**
* @param date - null if day title (0 - dd / 1 - mm / 2 - yy)
* @param position - position in item list
* @param item - view for date
*/
protected abstract void onDate(int[] date, int position, View item);
private void populateMonth() {
mItems = new ArrayList<String>();
for (String day : mDays) {
mItems.add(day);
mDaysShown++;
}
int firstDay = getDay(mCalendar.get(Calendar.DAY_OF_WEEK));
int prevDay;
if (mMonth == 0)
prevDay = daysInMonth(11) - firstDay + 1;
else
prevDay = daysInMonth(mMonth - 1) - firstDay + 1;
for (int i = 0; i < firstDay; i++) {
mItems.add(String.valueOf(prevDay + i));
mDaysLastMonth++;
mDaysShown++;
}
int daysInMonth = daysInMonth(mMonth);
for (int i = 1; i <= daysInMonth; i++) {
mItems.add(String.valueOf(i));
mDaysShown++;
}
mDaysNextMonth = 1;
while (mDaysShown % 7 != 0) {
mItems.add(String.valueOf(mDaysNextMonth));
mDaysShown++;
mDaysNextMonth++;
}
}
}

View File

@ -0,0 +1,94 @@
package sh.ftp.rocketninelabs.meditationassistant;
import java.util.Scanner;
public class NumToWord {
// array containing single digits
public static final String[] digits = {"", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine",
};
// array containing teens
public static final String[] teens = {"eleven", "twelve", "thirteen",
"fourteen", " fifteen", "sixteen", "seventeen", "eighteen",
"nineteen"};
// array containing tens numbers
public static final String[] tens = {"ten", "twenty", "therty", "fourty",
"fifty", "sixty", "seventy", "eighty", "ninety",};
// string for hundreds numbers
public static final String hundred = "hundred";
public static int tmpDigit, // temp number to store digits
tmpTeen, // temp to store teens numbers
tmpTen, // temp number to store tens
number, // number to be converted to words
result; // result number
// deciding whether a num is teen or not
public static boolean teen = false;
public static String getWord(int num) {
if (num > 0 && num < 10) {
result = num % 10;
return digits[result];
}
if (num > 10 && num < 20) {
result = num % 10;
return teens[result - 1];
}
if (num > 19 && num < 100) {
result = num / 10;
return tens[result - 1] + digits[num % 10];
}
return "";
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// getting user input
System.out.print("Please enter a number: ");
number = in.nextInt(); // number to be converted
// input validation
while (number <= 0) {
System.out.println("Number should be bigger than cero!");
System.out.print("Please enter a number:");
number = in.nextInt();
}
// converting single digits number
if (number > 0 && number < 10) {
result = number % 10;
System.out.println(digits[result]);
}
// converting teen numbers
if (number > 10 && number < 20) {
result = number % 10;
System.out.println(teens[result - 1]);
}
// converting from 20 to 100 numbers
if (number > 19 && number < 100) {
result = number / 10; // finding tens
System.out.print(tens[result - 1]);
number %= 10; // finding single digits
System.out.println(digits[number]);
}
// converting from 101 to 999
if (number > 100 && number < 1000) {
result = number / 100; // getting hundreds
// getting tens, and finding tens, and teens numbers
tmpTen = number % 100;
if (tmpTen > 1 && tmpTen < 20)// if teen go get it
{
tmpTeen = tmpTen % 10;
teen = true;
} else
// if not a teen split number
tmpTen /= 10;
// finding digits
tmpDigit = number % 10;
}
}
}

View File

@ -0,0 +1,42 @@
package sh.ftp.rocketninelabs.meditationassistant;
import org.json.JSONException;
import org.json.JSONObject;
public class Preset {
public String modeandduration = "";
public String delay = "";
public String startsound = "";
public String startsoundcustom = "";
public String intervalduration = "";
public String intervalsound = "";
public String intervalsoundcustom = "";
public String intervalcount = "";
public String completesound = "";
public String completesoundcustom = "";
public String ringtone = "";
public Boolean endless = false;
public Boolean vibrate = false;
public JSONObject export() {
JSONObject jobj = new JSONObject();
try {
jobj.put("modeandduration", modeandduration);
jobj.put("delay", delay);
jobj.put("startsound", startsound);
jobj.put("startsoundcustom", startsoundcustom);
jobj.put("intervalduration", intervalduration);
jobj.put("intervalsound", intervalsound);
jobj.put("intervalsoundcustom", intervalsoundcustom);
jobj.put("intervalcount", intervalcount);
jobj.put("completesound", completesound);
jobj.put("completesoundcustom", completesoundcustom);
jobj.put("ringtone", ringtone);
jobj.put("endless", endless);
jobj.put("vibrate", vibrate);
} catch (JSONException e1) {
e1.printStackTrace();
}
return jobj;
}
}

View File

@ -0,0 +1,811 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TabHost;
import android.widget.TextView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.analytics.GoogleAnalytics;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.TimeZone;
public class ProgressActivity extends FragmentActivity {
public SparseArray<SessionSQL> sessions_map = new SparseArray<SessionSQL>();
TabHost mTabHost;
ViewPager mViewPager;
ProgressPagerAdapter mPagerAdapter = null;
int pagePosition = 0;
private AlertDialog addSessionDialog = null;
private AdView av = null;
private int SESSIONS_FRAGMENT = 0;
private int CALENDAR_FRAGMENT = 1;
private int STATS_FRAGMENT = 2;
private SessionsFragment sessionsFragment = null;
private MeditationAssistant ma = null;
private MenuItem menuCalendarBack = null;
private MenuItem menuCalendarForward = null;
private String beingSet = "started";
private Button btnSetDateStarted = null;
private Button btnSetTimeStarted = null;
private Button btnSetDateCompleted = null;
private Button btnSetTimeCompleted = null;
private EditText editAddSessionMessage = null;
private int startedYear = -1;
private int startedMonth = -1;
private int startedDay = -1;
private int startedHour = -1;
private int startedMinute = -1;
private int completedYear = -1;
private int completedMonth = -1;
private int completedDay = -1;
private int completedHour = -1;
private int completedMinute = -1;
private DatePickerDialog.OnDateSetListener mDateSetListener =
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
if (beingSet.equals("started")) {
startedYear = year;
startedMonth = monthOfYear;
startedDay = dayOfMonth;
if (completedYear == -1 || completedMonth == -1 || completedDay == -1) {
completedYear = startedYear;
completedMonth = startedMonth;
completedDay = startedDay;
} else if (completedYear != -1 && completedMonth != -1 && completedDay != -1) {
Calendar c_started = Calendar.getInstance();
c_started.set(Calendar.YEAR, startedYear);
c_started.set(Calendar.MONTH, startedMonth);
c_started.set(Calendar.DAY_OF_MONTH, startedDay);
c_started.set(Calendar.HOUR_OF_DAY, 0);
c_started.set(Calendar.MINUTE, 0);
c_started.set(Calendar.SECOND, 0);
c_started.set(Calendar.MILLISECOND, 0);
Calendar c_completed = Calendar.getInstance();
c_completed.set(Calendar.YEAR, completedYear);
c_completed.set(Calendar.MONTH, completedMonth);
c_completed.set(Calendar.DAY_OF_MONTH, completedDay);
c_completed.set(Calendar.HOUR_OF_DAY, 0);
c_completed.set(Calendar.MINUTE, 0);
c_completed.set(Calendar.SECOND, 0);
c_completed.set(Calendar.MILLISECOND, 0);
if (c_started.getTimeInMillis() > c_completed.getTimeInMillis()) {
completedYear = startedYear;
completedMonth = startedMonth;
completedDay = startedDay;
}
}
} else {
completedYear = year;
completedMonth = monthOfYear;
completedDay = dayOfMonth;
}
updateDateAndTimeButtons();
}
};
private TimePickerDialog.OnTimeSetListener mTimeSetListener =
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
if (beingSet.equals("started")) {
startedHour = hourOfDay;
startedMinute = minute;
if (completedHour == -1 && completedMinute == -1) {
completedHour = startedHour;
completedMinute = startedMinute;
}
} else {
completedHour = hourOfDay;
completedMinute = minute;
}
updateDateAndTimeButtons();
}
};
private AlertDialog sessionDetailsDialog = null;
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.getApplication();
}
return ma;
}
public void updateDateAndTimeButtons() {
SimpleDateFormat sdf_date = new SimpleDateFormat("MMMM d",
Locale.getDefault());
SimpleDateFormat sdf_time = new SimpleDateFormat("h:mm a",
Locale.getDefault());
sdf_date.setTimeZone(TimeZone.getDefault());
sdf_time.setTimeZone(TimeZone.getDefault());
if (startedYear == -1 || startedMonth == -1 || startedDay == -1) {
btnSetDateStarted.setText(getString(R.string.setDate));
} else {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, startedYear);
c.set(Calendar.MONTH, startedMonth);
c.set(Calendar.DAY_OF_MONTH, startedDay);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
btnSetDateStarted.setText(sdf_date.format(c.getTime()));
}
if (completedYear == -1 || completedMonth == -1 || completedDay == -1) {
btnSetDateCompleted.setText(getString(R.string.setDate));
} else {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, completedYear);
c.set(Calendar.MONTH, completedMonth);
c.set(Calendar.DAY_OF_MONTH, completedDay);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
btnSetDateCompleted.setText(sdf_date.format(c.getTime()));
}
if (startedHour == -1 || startedMinute == -1) {
btnSetTimeStarted.setText(getString(R.string.setTime));
} else {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, startedHour);
c.set(Calendar.MINUTE, startedMinute);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
btnSetTimeStarted.setText(sdf_time.format(c.getTime()));
}
if (completedHour == -1 || completedMinute == -1) {
btnSetTimeCompleted.setText(getString(R.string.setTime));
} else {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, completedHour);
c.set(Calendar.MINUTE, completedMinute);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
btnSetTimeCompleted.setText(sdf_time.format(c.getTime()));
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(getMeditationAssistant().getMATheme());
setContentView(R.layout.activity_progress);
getActionBar().setDisplayHomeAsUpEnabled(true); /// todo: not necessary on settings activity why?
//getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if (getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant")) {
Log.d("MeditationAssistant", "Fetching ad");
av = (AdView) findViewById(R.id.adViewProgress);
av.setVisibility(View.VISIBLE);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
av.loadAd(adRequest);
}
mViewPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ProgressPagerAdapter(
getSupportFragmentManager());
mViewPager.setAdapter(mPagerAdapter);
/*ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// probably ignore this event
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
};
getActionBar().addTab(getActionBar().newTab()
.setText(getString(R.string.sessions))
.setTabListener(tabListener));
getActionBar().addTab(getActionBar().newTab()
.setText(getString(R.string.statistics))
.setTabListener(tabListener));
getActionBar().addTab(getActionBar().newTab()
.setText(getString(R.string.calendar))
.setTabListener(tabListener));*/
PagerTabStrip tabStrip = (PagerTabStrip) findViewById(R.id.titles);
tabStrip.setDrawFullUnderline(true);
if (getMeditationAssistant().getMAThemeString().equals("buddhism")) {
tabStrip.setBackgroundColor(getResources().getColor(R.color.buddhism_tab_background));
tabStrip.setTabIndicatorColor(getResources().getColor(R.color.buddhism_tab_color));
tabStrip.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
} else {
tabStrip.setTabIndicatorColor(getResources().getColor(android.R.color.holo_blue_dark));
}
/*ViewPagerIndicator titleIndicator = (TitlePageIndicator) findViewById(R.id.titles);
titleIndicator.setViewPager(mViewPager);
titleIndicator.setFooterIndicatorStyle(IndicatorStyle.Underline);
titleIndicator
.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position,
float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageSelected(int position) {
if (menuCalendarBack != null
&& menuCalendarForward != null) {
pagePosition = position;
}
}
});*/
String defaulttab = getMeditationAssistant().getPrefs().getString(
"pref_progresstab", "calendar");
if (defaulttab.equals("sessions")) {
mViewPager.setCurrentItem(SESSIONS_FRAGMENT, false);
} else if (defaulttab.equals("stats")) {
mViewPager.setCurrentItem(STATS_FRAGMENT, false);
} else {
mViewPager.setCurrentItem(CALENDAR_FRAGMENT, false);
}
if (getMeditationAssistant().sendUsageReports()) {
getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER);
}
}
public void goToSessionAtDate(int[] date) {
if (date != null) {
SessionSQL sessionsql = getMeditationAssistant().db.getSessionByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2]));
if (sessionsql != null) {
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(sessionsql._completed * 1000);
Date sess_date = cal.getTime();
if (getMeditationAssistant().db.numSessionsByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2])) > 1) {
if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) {
sessionDetailsDialog.dismiss();
}
SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy",
Locale.getDefault());
SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a",
Locale.getDefault());
ArrayList<SessionSQL> sessions = getMeditationAssistant().db.getSessionsByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2]));
final ArrayAdapter<String> sessionsDialogAdapter = new ArrayAdapter<String>(
this,
android.R.layout.select_dialog_item);
sessions_map.clear();
int session_index = 0;
for (Iterator<SessionSQL> i = sessions.iterator(); i.hasNext(); ) {
SessionSQL session = i.next();
Calendar cal2 = Calendar.getInstance();
cal2.setTimeInMillis(session._completed * 1000);
sessionsDialogAdapter.add(String.valueOf(session._length / 3600) + ":"
+ String.format("%02d", (session._length % 3600) / 60)
+ " - " + sdf2.format(cal2.getTime()));
sessions_map.put(session_index, session);
session_index++;
}
if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) {
sessionDetailsDialog.dismiss();
}
sessionDetailsDialog = new AlertDialog.Builder(this)
.setIcon(
getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconGoToToday})
.getResourceId(0, 0)
)
)
.setTitle(sdf.format(sess_date))
.setAdapter(sessionsDialogAdapter,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SessionSQL session = sessions_map.get(which);
if (session != null) {
showSessionPopup(session);
}
try {
dialog.dismiss();
} catch (Exception e) {
}
}
})
.create();
sessionDetailsDialog.show();
} else {
showSessionPopup(sessionsql);
}
/*mViewPager.setCurrentItem(SESSIONS_FRAGMENT, false);
Integer session_position = ((SessionAdapter) sessionsFragment.getListAdapter()).sessions_map.get(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2]));
if (session_position != null) {
Log.d("MeditationAssistant", "Position: " + String.valueOf(session_position));
sessionsFragment.getListView().smoothScrollToPosition(session_position);
}*/
}
}
}
private void showSessionPopup(SessionSQL sessionsql) {
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(sessionsql._completed * 1000);
Date sess_date = cal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy h:mm a",
Locale.getDefault());
sdf.setTimeZone(TimeZone.getDefault());
SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a",
Locale.getDefault());
sdf2.setTimeZone(TimeZone.getDefault());
String session_title = String.valueOf(sessionsql._length / 3600) + ":"
+ String.format("%02d", (sessionsql._length % 3600) / 60)
+ " - " + sdf.format(sess_date);
cal.setTimeInMillis(sessionsql._started * 1000);
String session_started = sdf2.format(cal.getTime());
View detailsView = LayoutInflater.from(this).inflate(
R.layout.session_details,
(ViewGroup) findViewById(R.id.sessionDetails_root));
TextView txtSessionDetailsStarted = (TextView) detailsView.findViewById(R.id.txtSessionDetailsStarted);
TextView txtSessionDetailsMessage = (TextView) detailsView.findViewById(R.id.txtSessionDetailsMessage);
txtSessionDetailsStarted.setText(String.format(getString(R.string.sessionStartedAt), session_started));
if (!sessionsql._message.trim().equals("")) {
txtSessionDetailsMessage.setText(sessionsql._message.trim());
} else {
View divSessionDetailsMessage = detailsView.findViewById(R.id.divSessionDetailsMessage);
divSessionDetailsMessage.setVisibility(View.GONE);
txtSessionDetailsMessage.setVisibility(View.GONE);
}
if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) {
sessionDetailsDialog.dismiss();
}
sessionDetailsDialog = new AlertDialog.Builder(this)
.setIcon(
getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconGoToToday})
.getResourceId(0, 0)
)
)
.setTitle(session_title)
.setView(detailsView)
.create();
sessionDetailsDialog.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.progress, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int i = item.getItemId();
if (i == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
} else if (i == R.id.addSession) {
if (addSessionDialog != null) {
try {
if (addSessionDialog.isShowing()) {
addSessionDialog.dismiss();
}
} catch (WindowManager.BadTokenException e) {
// Activity is not in the foreground
}
}
//debug
if (getMeditationAssistant()
.getTimeStartMeditate() > 0) {
getMeditationAssistant().shortToast(getString(R.string.addSessionMeditating));
return true;
}
startedYear = -1;
startedMonth = -1;
startedDay = -1;
startedHour = -1;
startedMinute = -1;
completedYear = -1;
completedMonth = -1;
completedDay = -1;
completedHour = -1;
completedMinute = -1;
View addSessionView = LayoutInflater.from(this).inflate(
R.layout.session_add,
(ViewGroup) findViewById(R.id.sessionAdd_root));
btnSetDateStarted = (Button) addSessionView.findViewById(R.id.btnSetDateStarted);
btnSetTimeStarted = (Button) addSessionView.findViewById(R.id.btnSetTimeStarted);
btnSetDateCompleted = (Button) addSessionView.findViewById(R.id.btnSetDateCompleted);
btnSetTimeCompleted = (Button) addSessionView.findViewById(R.id.btnSetTimeCompleted);
editAddSessionMessage = (EditText) addSessionView.findViewById(R.id.editAddSessionMessage);
btnSetDateStarted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
beingSet = "started";
DatePickerDialog dateDialog = null;
if (startedYear == -1 || startedMonth == -1 || startedDay == -1) {
Calendar c = Calendar.getInstance();
dateDialog = new DatePickerDialog(ProgressActivity.this,
mDateSetListener,
c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
} else {
dateDialog = new DatePickerDialog(ProgressActivity.this,
mDateSetListener,
startedYear, startedMonth, startedDay);
}
dateDialog.show();
}
});
btnSetTimeStarted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
beingSet = "started";
TimePickerDialog timeDialog = null;
if (startedHour == -1 || startedMinute == -1) {
Calendar c = Calendar.getInstance();
timeDialog = new TimePickerDialog(ProgressActivity.this,
mTimeSetListener,
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false);
} else {
timeDialog = new TimePickerDialog(ProgressActivity.this,
mTimeSetListener,
startedHour, startedMinute, false);
}
timeDialog.show();
}
});
btnSetDateCompleted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
beingSet = "completed";
DatePickerDialog dateDialog = null;
if (completedYear == -1 || completedMonth == -1 || completedDay == -1) {
Calendar c = Calendar.getInstance();
dateDialog = new DatePickerDialog(ProgressActivity.this,
mDateSetListener,
c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
} else {
dateDialog = new DatePickerDialog(ProgressActivity.this,
mDateSetListener,
completedYear, completedMonth, completedDay);
}
dateDialog.show();
}
});
btnSetTimeCompleted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
beingSet = "completed";
TimePickerDialog timeDialog = null;
if (completedHour == -1 || completedMinute == -1) {
Calendar c = Calendar.getInstance();
timeDialog = new TimePickerDialog(ProgressActivity.this,
mTimeSetListener,
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false);
} else {
timeDialog = new TimePickerDialog(ProgressActivity.this,
mTimeSetListener,
completedHour, completedMinute, false);
}
timeDialog.show();
}
});
updateDateAndTimeButtons();
addSessionDialog = new AlertDialog.Builder(this)
.setIcon(
getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconNew})
.getResourceId(0, 0)
)
)
.setTitle(getString(R.string.addSession))
.setView(addSessionView)
.setPositiveButton(getString(R.string.add), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface,
int which) {
// Overridden later
}
})
.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface,
int which) {
dialogInterface.dismiss();
}
})
.create();
addSessionDialog.show();
Button saveButton = addSessionDialog.getButton(AlertDialog.BUTTON_POSITIVE);
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (startedYear == -1 || startedMonth == -1 || startedDay == -1 || startedHour == -1 || startedMinute == -1 || completedYear == -1 || completedMonth == -1 || completedDay == -1 || completedHour == -1 || completedMinute == -1) {
getMeditationAssistant().shortToast(getString(R.string.invalidDateOrTime));
} else {
Calendar c_started = Calendar.getInstance();
c_started.set(Calendar.YEAR, startedYear);
c_started.set(Calendar.MONTH, startedMonth);
c_started.set(Calendar.DAY_OF_MONTH, startedDay);
c_started.set(Calendar.HOUR_OF_DAY, startedHour);
c_started.set(Calendar.MINUTE, startedMinute);
c_started.set(Calendar.SECOND, 0);
c_started.set(Calendar.MILLISECOND, 0);
Calendar c_completed = Calendar.getInstance();
c_completed.set(Calendar.YEAR, completedYear);
c_completed.set(Calendar.MONTH, completedMonth);
c_completed.set(Calendar.DAY_OF_MONTH, completedDay);
c_completed.set(Calendar.HOUR_OF_DAY, completedHour);
c_completed.set(Calendar.MINUTE, completedMinute);
c_completed.set(Calendar.SECOND, 0);
c_completed.set(Calendar.MILLISECOND, 0);
if (c_started.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_completed.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_completed.getTimeInMillis() <= c_started.getTimeInMillis()) {
getMeditationAssistant().shortToast(getString(R.string.invalidDateOrTime));
} else if (getMeditationAssistant().db
.getSessionByStarted(c_started.getTimeInMillis() / 1000) == null) {
getMeditationAssistant().getMediNET().resetSession();
getMeditationAssistant().getMediNET().session.started = c_started.getTimeInMillis() / 1000;
getMeditationAssistant().getMediNET().session.length = ((c_completed.getTimeInMillis() / 1000) - (c_started.getTimeInMillis() / 1000));
getMeditationAssistant().getMediNET().session.completed = c_completed.getTimeInMillis() / 1000;
getMeditationAssistant().getMediNET().session.message = editAddSessionMessage.getText().toString().trim();
getMeditationAssistant().getMediNET().saveSession(true, false);
addSessionDialog.dismiss();
if (sessionsFragment != null) {
sessionsFragment.refreshSessionList();
}
/*if (calendarFragment != null) {
calendarFragment.refreshMonthDisplay();
}*/
} else {
getMeditationAssistant().shortToast(getString(R.string.addSessionExists));
}
}
}
});
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStart() {
super.onStart();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}
@Override
public void onPause() {
if (av != null) {
av.pause();
}
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (av != null) {
av.resume();
}
}
@Override
public void onDestroy() {
if (av != null) {
av.destroy();
}
super.onDestroy();
}
class ProgressPagerAdapter extends FragmentPagerAdapter {
private final String[] ProgressPages = new String[]{
getString(R.string.sessions), getString(R.string.calendar), getString(R.string.statistics)};
public ProgressPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ProgressPages.length;
}
@Override
public Fragment getItem(int position) {
if (position == SESSIONS_FRAGMENT) {
sessionsFragment = new SessionsFragment();
return sessionsFragment;
} else if (position == CALENDAR_FRAGMENT) {
CalendarFragment calendarFragment = new CalendarFragment();
return calendarFragment;
} else if (position == STATS_FRAGMENT) {
return new StatsFragment();
} else {
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
return ProgressPages[position % ProgressPages.length].toUpperCase();
}
}
}
/*
public class ProgressActivity extends FragmentActivity
implements ItemListFragment.Callbacks {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
private boolean mTwoPane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((ItemListFragment) getSupportFragmentManager()
.findFragmentById(R.id.item_list))
.setActivateOnItemClick(true);
}
}
/**
* Callback method from {@link ItemListFragment.Callbacks}
* indicating that the item with the given ID was selected.
@Override
public void onItemSelected(String id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.apply();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
}
*/

View File

@ -0,0 +1,495 @@
package sh.ftp.rocketninelabs.meditationassistant;
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed 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.
*/
import android.content.Context;
import android.hardware.SensorManager;
import android.util.FloatMath;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
/**
* This class encapsulates scrolling. The duration of the scroll
* can be passed in the constructor and specifies the maximum time that
* the scrolling animation should take. Past this time, the scrolling is
* automatically moved to its final stage and computeScrollOffset()
* will always return false to indicate that scrolling is over.
*/
public class Scroller {
private static final int DEFAULT_DURATION = 250;
private static final int SCROLL_MODE = 0;
private static final int FLING_MODE = 1;
private static final int NB_SAMPLES = 100;
private static final float[] SPLINE = new float[NB_SAMPLES + 1];
private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
@SuppressWarnings("FieldCanBeLocal")
private static float ALPHA = 800; // pixels / seconds
private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance)
private static float END_TENSION = 1.0f - START_TENSION;
private static float sViscousFluidScale;
private static float sViscousFluidNormalize;
static {
float x_min = 0.0f;
for (int i = 0; i <= NB_SAMPLES; i++) {
final float t = (float) i / NB_SAMPLES;
float x_max = 1.0f;
float x, tx, coef;
while (true) {
x = x_min + (x_max - x_min) / 2.0f;
coef = 3.0f * x * (1.0f - x);
tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x;
if (Math.abs(tx - t) < 1E-5) break;
if (tx > t) x_max = x;
else x_min = x;
}
final float d = coef + x * x * x;
SPLINE[i] = d;
}
SPLINE[NB_SAMPLES] = 1.0f;
// This controls the viscous fluid effect (how much of it)
sViscousFluidScale = 8.0f;
// must be set to 1.0 (used in viscousFluid())
sViscousFluidNormalize = 1.0f;
sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
}
private final float mPpi;
private int mMode;
private int mStartX;
private int mStartY;
private int mFinalX;
private int mFinalY;
private int mMinX;
private int mMaxX;
private int mMinY;
private int mMaxY;
private int mCurrX;
private int mCurrY;
private long mStartTime;
private int mDuration;
private float mDurationReciprocal;
private float mDeltaX;
private float mDeltaY;
private boolean mFinished;
private Interpolator mInterpolator;
private boolean mFlywheel;
private float mVelocity;
private float mDeceleration;
/**
* Create a Scroller with the default duration and interpolator.
*/
public Scroller(Context context) {
this(context, null);
}
/**
* Create a Scroller with the specified interpolator. If the interpolator is
* null, the default (viscous) interpolator will be used. "Flywheel" behavior will
* be in effect for apps targeting Honeycomb or newer.
*/
public Scroller(Context context, Interpolator interpolator) {
this(context, interpolator, true);
}
/**
* Create a Scroller with the specified interpolator. If the interpolator is
* null, the default (viscous) interpolator will be used. Specify whether or
* not to support progressive "flywheel" behavior in flinging.
*/
public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
mFinished = true;
mInterpolator = interpolator;
mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
mFlywheel = flywheel;
}
static float viscousFluid(float x) {
x *= sViscousFluidScale;
if (x < 1.0f) {
x -= (1.0f - (float) Math.exp(-x));
} else {
float start = 0.36787944117f; // 1/e == exp(-1)
x = 1.0f - (float) Math.exp(1.0f - x);
x = start + x * (1.0f - start);
}
x *= sViscousFluidNormalize;
return x;
}
/**
* The amount of friction applied to flings. The default value
* is {@link android.view.ViewConfiguration#getScrollFriction}.
*
* @param friction A scalar dimension-less value representing the coefficient of
* friction.
*/
public final void setFriction(float friction) {
mDeceleration = computeDeceleration(friction);
}
private float computeDeceleration(float friction) {
return SensorManager.GRAVITY_EARTH // g (m/s^2)
* 39.37f // inch/meter
* mPpi // pixels per inch
* friction;
}
/**
* Returns whether the scroller has finished scrolling.
*
* @return True if the scroller has finished scrolling, false otherwise.
*/
public final boolean isFinished() {
return mFinished;
}
/**
* Force the finished field to a particular value.
*
* @param finished The new finished value.
*/
public final void forceFinished(boolean finished) {
mFinished = finished;
}
/**
* Returns how long the scroll event will take, in milliseconds.
*
* @return The duration of the scroll in milliseconds.
*/
public final int getDuration() {
return mDuration;
}
/**
* Returns the current X offset in the scroll.
*
* @return The new X offset as an absolute distance from the origin.
*/
public final int getCurrX() {
return mCurrX;
}
/**
* Returns the current Y offset in the scroll.
*
* @return The new Y offset as an absolute distance from the origin.
*/
public final int getCurrY() {
return mCurrY;
}
/**
* Returns the current velocity.
*
* @return The original velocity less the deceleration. Result may be
* negative.
*/
public float getCurrVelocity() {
return mVelocity - mDeceleration * timePassed() / 2000.0f;
}
/**
* Returns the start X offset in the scroll.
*
* @return The start X offset as an absolute distance from the origin.
*/
public final int getStartX() {
return mStartX;
}
/**
* Returns the start Y offset in the scroll.
*
* @return The start Y offset as an absolute distance from the origin.
*/
public final int getStartY() {
return mStartY;
}
/**
* Returns where the scroll will end. Valid only for "fling" scrolls.
*
* @return The final X offset as an absolute distance from the origin.
*/
public final int getFinalX() {
return mFinalX;
}
/**
* Sets the final position (X) for this scroller.
*
* @param newX The new X offset as an absolute distance from the origin.
* @see #extendDuration(int)
* @see #setFinalY(int)
*/
public void setFinalX(int newX) {
mFinalX = newX;
mDeltaX = mFinalX - mStartX;
mFinished = false;
}
/**
* Returns where the scroll will end. Valid only for "fling" scrolls.
*
* @return The final Y offset as an absolute distance from the origin.
*/
public final int getFinalY() {
return mFinalY;
}
/**
* Sets the final position (Y) for this scroller.
*
* @param newY The new Y offset as an absolute distance from the origin.
* @see #extendDuration(int)
* @see #setFinalX(int)
*/
public void setFinalY(int newY) {
mFinalY = newY;
mDeltaY = mFinalY - mStartY;
mFinished = false;
}
/**
* Call this when you want to know the new location. If it returns true,
* the animation is not yet finished. loc will be altered to provide the
* new location.
*/
public boolean computeScrollOffset() {
if (mFinished) {
return false;
}
int timePassed = (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime);
if (timePassed < mDuration) {
switch (mMode) {
case SCROLL_MODE:
float x = timePassed * mDurationReciprocal;
if (mInterpolator == null)
x = viscousFluid(x);
else
x = mInterpolator.getInterpolation(x);
mCurrX = mStartX + Math.round(x * mDeltaX);
mCurrY = mStartY + Math.round(x * mDeltaY);
break;
case FLING_MODE:
final float t = (float) timePassed / mDuration;
final int index = (int) (NB_SAMPLES * t);
final float t_inf = (float) index / NB_SAMPLES;
final float t_sup = (float) (index + 1) / NB_SAMPLES;
final float d_inf = SPLINE[index];
final float d_sup = SPLINE[index + 1];
final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf);
mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
// Pin to mMinX <= mCurrX <= mMaxX
mCurrX = Math.min(mCurrX, mMaxX);
mCurrX = Math.max(mCurrX, mMinX);
mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
// Pin to mMinY <= mCurrY <= mMaxY
mCurrY = Math.min(mCurrY, mMaxY);
mCurrY = Math.max(mCurrY, mMinY);
if (mCurrX == mFinalX && mCurrY == mFinalY) {
mFinished = true;
}
break;
}
} else {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
return true;
}
/**
* Start scrolling by providing a starting point and the distance to travel.
* The scroll will use the default value of 250 milliseconds for the
* duration.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
* @param startY Starting vertical scroll offset in pixels. Positive numbers
* will scroll the content up.
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
*/
public void startScroll(int startX, int startY, int dx, int dy) {
startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}
/**
* Start scrolling by providing a starting point and the distance to travel.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
* @param startY Starting vertical scroll offset in pixels. Positive numbers
* will scroll the content up.
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
* @param duration Duration of the scroll in milliseconds.
*/
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
}
/**
* Start scrolling based on a fling gesture. The distance travelled will
* depend on the initial velocity of the fling.
*
* @param startX Starting point of the scroll (X)
* @param startY Starting point of the scroll (Y)
* @param velocityX Initial velocity of the fling (X) measured in pixels per
* second.
* @param velocityY Initial velocity of the fling (Y) measured in pixels per
* second
* @param minX Minimum X value. The scroller will not scroll past this
* point.
* @param maxX Maximum X value. The scroller will not scroll past this
* point.
* @param minY Minimum Y value. The scroller will not scroll past this
* point.
* @param maxY Maximum Y value. The scroller will not scroll past this
* point.
*/
public void fling(int startX, int startY, int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) {
// Continue a scroll or fling in progress
if (mFlywheel && !mFinished) {
float oldVel = getCurrVelocity();
float dx = (float) (mFinalX - mStartX);
float dy = (float) (mFinalY - mStartY);
float hyp = FloatMath.sqrt(dx * dx + dy * dy);
float ndx = dx / hyp;
float ndy = dy / hyp;
float oldVelocityX = ndx * oldVel;
float oldVelocityY = ndy * oldVel;
if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
Math.signum(velocityY) == Math.signum(oldVelocityY)) {
velocityX += oldVelocityX;
velocityY += oldVelocityY;
}
}
mMode = FLING_MODE;
mFinished = false;
float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
mVelocity = velocity;
final double l = Math.log(START_TENSION * velocity / ALPHA);
mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0)));
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
int totalDistance =
(int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l));
mMinX = minX;
mMaxX = maxX;
mMinY = minY;
mMaxY = maxY;
mFinalX = startX + Math.round(totalDistance * coeffX);
// Pin to mMinX <= mFinalX <= mMaxX
mFinalX = Math.min(mFinalX, mMaxX);
mFinalX = Math.max(mFinalX, mMinX);
mFinalY = startY + Math.round(totalDistance * coeffY);
// Pin to mMinY <= mFinalY <= mMaxY
mFinalY = Math.min(mFinalY, mMaxY);
mFinalY = Math.max(mFinalY, mMinY);
}
/**
* Stops the animation. Contrary to {@link #forceFinished(boolean)},
* aborting the animating cause the scroller to move to the final x and y
* position
*
* @see #forceFinished(boolean)
*/
public void abortAnimation() {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
/**
* Extend the scroll animation. This allows a running animation to scroll
* further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
*
* @param extend Additional time to scroll in milliseconds.
* @see #setFinalX(int)
* @see #setFinalY(int)
*/
public void extendDuration(int extend) {
int passed = timePassed();
mDuration = passed + extend;
mDurationReciprocal = 1.0f / mDuration;
mFinished = false;
}
/**
* Returns the time elapsed since the beginning of the scrolling.
*
* @return The elapsed time in milliseconds.
*/
public int timePassed() {
return (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime);
}
/**
* @hide
*/
public boolean isScrollingInDirection(float xvel, float yvel) {
return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
Math.signum(yvel) == Math.signum(mFinalY - mStartY);
}
}

View File

@ -0,0 +1,84 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
public class SessionAdapter extends ArrayAdapter<SessionSQL> {
public Map<String, Integer> sessions_map = new HashMap<String, Integer>();
// private final ArrayList<MeditationSession> sessions;
private Context context = null;
private ArrayList<SessionSQL> sessions = null;
public SessionAdapter(Context context, ArrayList<SessionSQL> sess) {
super(context, R.layout.activity_sessions_item, sess);
this.context = context;
this.sessions = sess;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_sessions_item,
parent, false);
TextView txtSessionLength = (TextView) rowView
.findViewById(R.id.session_length);
TextView txtSessionStarted = (TextView) rowView
.findViewById(R.id.session_started);
TextView txtSessionStartedTime = (TextView) rowView
.findViewById(R.id.session_started_time);
txtSessionLength
.setText(String.valueOf(sessions.get(position)._length / 3600)
+ ":"
+ String.format("%02d",
(sessions.get(position)._length % 3600) / 60));
// txtSessionLength.setText(String.format("%d:%02d",
// sessions.get(position).length/3600,
// (sessions.get(position).length%3600)/60));
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis((sessions.get(position)._started + sessions
.get(position)._length) * 1000);
Date date = cal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("h:mm a", Locale.getDefault());
SimpleDateFormat sdf2 = new SimpleDateFormat("d MMM yyyy", Locale.getDefault());
SimpleDateFormat sdf3 = new SimpleDateFormat("d-M-yyyy", Locale.getDefault());
sdf.setTimeZone(TimeZone.getDefault());
sdf2.setTimeZone(TimeZone.getDefault());
sdf3.setTimeZone(TimeZone.getDefault());
// sessions.get(position).date = sdf.format(date);
// sessions.get(position).time = sdf2.format(date);
txtSessionStartedTime.setText(sdf.format(date));
txtSessionStarted.setText(sdf2.format(date));
// Change icon based on name
// String s = values[position];
// Log.d("MeditationAssistant", "LV: " + s);
/*if (!sessions_map.containsKey(sdf3.format(date))) {
Log.d("MeditationAssistant", "Session position: " + sdf3.format(date) + " - " + String.valueOf(position));
sessions_map.put(sdf3.format(date), position);
}*/
return rowView;
}
}

View File

@ -0,0 +1,42 @@
package sh.ftp.rocketninelabs.meditationassistant;
public class SessionSQL {
public Long _id;
public Long _started;
public Long _completed;
public Long _length;
public String _message;
public Long _isposted;
public Long _streakday;
public SessionSQL() {
}
public SessionSQL(Long id, Long started, Long completed, Long length, String message,
Long isposted, Long streakday) {
this._id = id;
this._started = started;
this._completed = completed;
this._length = length;
this._message = message;
this._isposted = isposted;
this._streakday = streakday;
}
public SessionSQL(Long started, Long completed, Long length, String message, Long isposted, Long streakday) {
this._started = started;
this._completed = completed;
this._length = length;
this._message = message;
this._isposted = isposted;
this._streakday = streakday;
}
public Long getID() {
return this._id;
}
public void setID(Long id) {
this._id = id;
}
}

View File

@ -0,0 +1,273 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ListView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class SessionsFragment extends ListFragment {
public MeditationAssistant ma = null;
AlertDialog sessionDialog = null;
AlertDialog sessionDetailsDialog = null;
SessionSQL selected_session = null;
String session_title = null;
String session_started = null;
SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("sessionsupdate")) {
Log.d("MeditationAssistant", "Got sessions update, refreshing SessionsFragment");
refreshSessionList();
}
}
};
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) getActivity().getApplication();
}
return ma;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setOnItemLongClickListener(new android.widget.AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(android.widget.AdapterView<?> adapterView, View view, int position, long id) {
if (sessionDetailsDialog != null) {
try {
if (sessionDetailsDialog.isShowing()) {
sessionDetailsDialog.dismiss();
}
} catch (WindowManager.BadTokenException e) {
// Activity is not in the foreground
}
}
if (sessionDialog != null) {
try {
if (sessionDialog.isShowing()) {
sessionDialog.dismiss();
}
} catch (WindowManager.BadTokenException e) {
// Activity is not in the foreground
}
}
selected_session = (SessionSQL) getListView().getItemAtPosition(position);
setSessionDialogDetails();
sessionDialog = new AlertDialog.Builder(getActivity())
.setIcon(
getActivity().getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconGoToToday})
.getResourceId(0, 0)
)
)
.setTitle(session_title)
.setItems(R.array.session_actions,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
if (which == 0) {
if (getMeditationAssistant()
.getTimeStartMeditate() > 0) {
getActivity().runOnUiThread(
new Runnable() {
@Override
public void run() {
getMeditationAssistant()
.shortToast(
getString(R.string.sessionNotPostedMeditating));
}
}
);
} else {
getMeditationAssistant().getMediNET().session.started = selected_session._started;
getMeditationAssistant().getMediNET().session.length = selected_session._length;
getMeditationAssistant().getMediNET().session.message = selected_session._message;
getMeditationAssistant().getMediNET().session.streakday = selected_session._streakday;
getMeditationAssistant().getMediNET()
.postSession(true,
getActivity());
}
} else {
AlertDialog deleteDialog = new AlertDialog.Builder(
getActivity())
.setIcon(
getActivity().getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconGoToToday})
.getResourceId(0, 0)
)
)
.setTitle(session_title)
.setItems(
R.array.session_delete_actions,
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
if (which == 0
|| which == 1) {
// Delete
// locally
getMeditationAssistant().db
.deleteSession(selected_session);
getMeditationAssistant()
.shortToast(
getString(R.string.sessionDeletedLocally));
}
if (which == 0
|| which == 2) {
// Delete on
// Medinet
getMeditationAssistant()
.getMediNET()
.deleteSessionByStarted(
selected_session._started);
}
if (which == 0
|| which == 1) {
refreshSessionList();
}
}
}
).create();
deleteDialog.show();
}
}
}
).create();
sessionDialog.show();
return true;
}
});
refreshSessionList();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
if (sessionDetailsDialog != null) {
try {
if (sessionDetailsDialog.isShowing()) {
sessionDetailsDialog.dismiss();
}
} catch (WindowManager.BadTokenException e) {
// Activity is not in the foreground
}
}
if (sessionDialog != null) {
try {
if (sessionDialog.isShowing()) {
sessionDialog.dismiss();
}
} catch (WindowManager.BadTokenException e) {
// Activity is not in the foreground
}
}
selected_session = (SessionSQL) l.getItemAtPosition(position);
setSessionDialogDetails();
View detailsView = LayoutInflater.from(getActivity()).inflate(
R.layout.session_details,
(ViewGroup) getActivity().findViewById(R.id.sessionDetails_root));
TextView txtSessionDetailsStarted = (TextView) detailsView.findViewById(R.id.txtSessionDetailsStarted);
TextView txtSessionDetailsMessage = (TextView) detailsView.findViewById(R.id.txtSessionDetailsMessage);
txtSessionDetailsStarted.setText(String.format(getString(R.string.sessionStartedAt), session_started));
if (!selected_session._message.trim().equals("")) {
txtSessionDetailsMessage.setText(selected_session._message.trim());
} else {
View divSessionDetailsMessage = detailsView.findViewById(R.id.divSessionDetailsMessage);
divSessionDetailsMessage.setVisibility(View.GONE);
txtSessionDetailsMessage.setVisibility(View.GONE);
}
sessionDetailsDialog = new AlertDialog.Builder(getActivity())
.setIcon(
getActivity().getResources().getDrawable(
getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true),
new int[]{R.attr.actionIconGoToToday})
.getResourceId(0, 0)
)
)
.setTitle(session_title)
.setView(detailsView)
.create();
sessionDetailsDialog.show();
}
private void setSessionDialogDetails() {
SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy h:mm a",
Locale.getDefault());
sdf.setTimeZone(TimeZone.getDefault());
SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a",
Locale.getDefault());
sdf2.setTimeZone(TimeZone.getDefault());
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(selected_session._completed * 1000);
Date date = cal.getTime();
session_title = String.valueOf(selected_session._length / 3600) + ":"
+ String.format("%02d", (selected_session._length % 3600) / 60)
+ " - " + sdf.format(date);
cal.setTimeInMillis(selected_session._started * 1000);
session_started = sdf2.format(cal.getTime());
}
public void refreshSessionList() {
setListAdapter(new SessionAdapter(getActivity(),
getMeditationAssistant().db.getAllSessions()));
}
@Override
public void onPause() {
getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onPause();
}
@Override
public void onResume() {
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onResume();
}
}

View File

@ -0,0 +1,745 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.RingtonePreference;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.gms.analytics.GoogleAnalytics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p/>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
@SuppressWarnings("deprecation")
public class SettingsActivity extends PreferenceActivity {
/**
* Determines whether to always show the simplified settings UI, where
* settings are presented in a single list. When false, settings are shown
* as a master/detail two-pane view on tablets. When true, a single pane is
* shown on tablets.
*/
private static final boolean ALWAYS_SIMPLE_PREFS = false;
public Boolean initialThemeChange = true;
public Boolean initialTimePickerChange = true;
public Boolean initialSoundChangeStart = true;
public Boolean initialSoundChangeInterval = true;
public Boolean initialSoundChangeFinish = true;
public SessionPreferenceFragment sessionPreferenceFragment = null;
public ReminderPreferenceFragment reminderPreferenceFragment = null;
public MeditationPreferenceFragment meditationPreferenceFragment = null;
public MediNETPreferenceFragment medinetPreferenceFragment = null;
public MiscellaneousPreferenceFragment miscellaneousPreferenceFragment = null;
int PREF_SOUND_START = 1;
int PREF_SOUND_INTERVAL = 3;
int PREF_SOUND_FINISH = 2;
private MeditationAssistant ma = null;
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
if (preference instanceof CheckBoxPreference) {
if (preference.getKey().equals("pref_daily_reminder")) {
Intent intent = new Intent();
intent.setAction(MeditationAssistant.ACTION_UPDATED);
sendBroadcast(intent);
} else if (preference.getKey().equals("pref_usetimepicker")) {
if (!initialTimePickerChange) {
Toast.makeText(SettingsActivity.this, getString(R.string.restartAppApplyTimePicker), Toast.LENGTH_SHORT).show();
}
initialTimePickerChange = false;
}
return true;
}
String stringValue = "";
if (!preference.getKey().equals("pref_presetsettings")) {
stringValue = value.toString();
}
if (preference.getKey().equals("pref_presetsettings")) {
HashSet<String> presetSettings = (HashSet<String>) value;
if (presetSettings.size() == 0) {
preference.setSummary(getString(R.string.disabled));
} else {
List<String> presetsettings = Arrays.asList(getResources().getStringArray(R.array.presetsettings));
List<String> presetsettings_values = Arrays.asList(getResources().getStringArray(R.array.presetsettings_values));
String presetsummary = "";
for (Iterator<String> preseti = presetsettings_values.iterator(); preseti.hasNext(); ) {
String preset = preseti.next();
if (presetSettings.contains(preset)) {
if (presetsummary != "") {
presetsummary += ", ";
}
presetsummary += presetsettings.get(presetsettings_values.indexOf(preset));
}
}
preference.setSummary(presetsummary);
}
} else if (preference instanceof ListPreference || preference instanceof ListPreferenceSound) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: "Gong"
); // TODO: Don't hardcode sound names
if (listPreference.getKey().equals("pref_theme")) {
if (!initialThemeChange) {
Toast.makeText(SettingsActivity.this, getString(R.string.restartAppApplyTheme), Toast.LENGTH_SHORT).show();
}
initialThemeChange = false;
} else if (listPreference.getKey().equals("pref_meditation_sound_start")) {
if (stringValue.equals("custom")) {
if (!initialSoundChangeStart) {
Intent intent = new Intent(
Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
Intent finalIntent = Intent.createChooser(
intent, getString(R.string.selectSound));
startActivityForResult(finalIntent, PREF_SOUND_START);
}
preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start_custom", "")));
}
initialSoundChangeStart = false;
} else if (listPreference.getKey().equals("pref_meditation_sound_interval")) {
if (stringValue.equals("custom")) {
if (!initialSoundChangeInterval) {
Intent intent = new Intent(
Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
Intent finalIntent = Intent.createChooser(
intent, getString(R.string.selectSound));
startActivityForResult(finalIntent, PREF_SOUND_INTERVAL);
}
preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval_custom", "")));
}
initialSoundChangeInterval = false;
} else if (listPreference.getKey().equals("pref_meditation_sound_finish")) {
if (stringValue.equals("custom")) {
if (!initialSoundChangeFinish) {
Intent intent = new Intent(
Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
Intent finalIntent = Intent.createChooser(
intent, getString(R.string.selectSound));
startActivityForResult(finalIntent, PREF_SOUND_FINISH);
}
preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish_custom", "")));
}
initialSoundChangeFinish = false;
}
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
//preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else if (preference instanceof TimePreference) {
if (preference.getKey().equals("pref_daily_reminder_time")) {
String timeValue = "";
try {
String[] timeValueSplit = ((stringValue != null && stringValue != "") ? stringValue : "19:00").split(":");
String ampm = "AM";
if (Integer.valueOf(timeValueSplit[0]) >= 12) {
timeValueSplit[0] = String.valueOf(Integer.valueOf(timeValueSplit[0]) - 12);
ampm = "PM";
}
if (Integer.valueOf(timeValueSplit[0]) == 0) {
timeValueSplit[0] = "12";
}
timeValue = String.valueOf(Integer.valueOf(timeValueSplit[0])) + ":"
+ String.format("%02d", Integer.valueOf(timeValueSplit[1])) + " " + ampm;
} catch (Exception e) {
e.printStackTrace();
}
preference.setSummary(timeValue);
Intent intent = new Intent();
intent.setAction(MeditationAssistant.ACTION_UPDATED);
sendBroadcast(intent);
} else { // pref_session_delay and pref_session_interval
Log.d("MeditationAssistant", preference.getKey() + " value: " + String.valueOf(stringValue));
String timeValue = "";
Boolean isDisabled = false;
try {
String[] timeValueSplit = ((stringValue != null && stringValue != "") ? stringValue : (preference.getKey().equals("pref_session_delay") ? "00:15" : "00:00")).split(":");
timeValue = String.valueOf((int) Math.floor(Integer.valueOf(timeValueSplit[0]) / 60)) + ":"
+ String.format("%02d", Integer.valueOf(timeValueSplit[0]) % 60) + ":"
+ String.format("%02d", Integer.valueOf(timeValueSplit[1]));
isDisabled = (Integer.valueOf(timeValueSplit[0]) == 0 && Integer.valueOf(timeValueSplit[1]) == 0);
} catch (Exception e) {
e.printStackTrace();
}
preference.setSummary(isDisabled ? getString(R.string.disabled) : timeValue);
if (preference.getKey().equals("pref_session_interval")) {
ListPreferenceSound prefIntervalSound = (ListPreferenceSound) (sessionPreferenceFragment == null ? findPreference("pref_meditation_sound_interval") : sessionPreferenceFragment.findPreference("pref_meditation_sound_interval"));
prefIntervalSound.setEnabled(!isDisabled);
EditTextPreference prefIntervalCount = (EditTextPreference) (sessionPreferenceFragment == null ? findPreference("pref_interval_count") : sessionPreferenceFragment.findPreference("pref_interval_count"));
prefIntervalCount.setEnabled(!isDisabled);
}
}
} else if (preference.getKey().equals("pref_interval_count")) {
if (stringValue == null || String.valueOf(stringValue).trim().equals("")) {
stringValue = "0";
}
if (Integer.valueOf(stringValue) <= 0) {
preference.setSummary(getString(R.string.unlimited));
} else {
preference.setSummary(getResources().getQuantityString(
R.plurals.numtimes, Integer.valueOf(stringValue),
String.valueOf(Integer.valueOf(stringValue))
));
}
} else if (preference.getKey().equals("pref_daily_reminder_text")) {
String reminderText = getString(R.string.reminderText);
if (stringValue != null && !String.valueOf(stringValue).trim().equals("")) {
reminderText = String.valueOf(stringValue).trim();
}
preference.setSummary(reminderText);
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
private Long uploadsessions_lastlick = (long) 0;
private Long importsessions_lastlick = (long) 0;
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Determines whether the simplified settings UI should be shown. This is
* true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
* doesn't have newer APIs like {@link PreferenceFragment}, or the device
* doesn't have an extra-large screen. In these cases, a single-pane
* "simplified" settings UI should be shown.
*/
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private static boolean isSimplePreferences(Context context) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|| !isXLargeTablet(context);
}
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(getMeditationAssistant().getMATheme());
if (getMeditationAssistant().sendUsageReports()) {
getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER);
}
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStart(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (getMeditationAssistant().sendUsageReports()) {
GoogleAnalytics.getInstance(this).reportActivityStop(this);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri d = null;
String pref = "";
String pref_key = "";
if (requestCode == PREF_SOUND_START) {
pref_key = "pref_meditation_sound_start";
pref = "pref_meditation_sound_start_custom";
} else if (requestCode == PREF_SOUND_INTERVAL) {
pref_key = "pref_meditation_sound_interval";
pref = "pref_meditation_sound_interval_custom";
} else if (requestCode == PREF_SOUND_FINISH) {
pref_key = "pref_meditation_sound_finish";
pref = "pref_meditation_sound_finish_custom";
} else {
return;
}
if (data != null) {
d = data.getData();
if (d != null) {
if (!d.toString().equals("")) {
getMeditationAssistant().getPrefs().edit().putString(pref, FileUtils.getPath(this, d)).apply();
}
}
}
if (requestCode == PREF_SOUND_START) {
initialSoundChangeStart = true;
} else if (requestCode == PREF_SOUND_INTERVAL) {
initialSoundChangeInterval = true;
} else if (requestCode == PREF_SOUND_FINISH) {
initialSoundChangeFinish = true;
}
ListPreferenceSound prefMeditationSound = (ListPreferenceSound) (sessionPreferenceFragment == null ? findPreference(pref_key) : sessionPreferenceFragment.findPreference(pref_key));
prefMeditationSound.getOnPreferenceChangeListener().onPreferenceChange(prefMeditationSound, getMeditationAssistant().getPrefs().getString(pref_key, "gong"));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent = null;
int i = item.getItemId();
if (i == R.id.action_about) {
intent = new Intent(this, AboutActivity.class);
startActivity(intent);
return true;
} else if (i == R.id.action_accountsettings) {
Intent openActivity = new Intent(this,
MediNETActivity.class);
openActivity.putExtra("page", "account");
startActivity(openActivity);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
}
void setupSoundPreferences(PreferenceFragment preferenceFragment) {
String[] meditation_sounds = getResources().getStringArray(R.array.meditation_sounds);
String[] meditation_sounds_values = getResources().getStringArray(R.array.meditation_sounds_values);
ListPreferenceSound prefMeditationSoundStart = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_start") : preferenceFragment.findPreference("pref_meditation_sound_start"));
prefMeditationSoundStart.setEntries(meditation_sounds);
prefMeditationSoundStart.setEntryValues(meditation_sounds_values);
ListPreferenceSound prefMeditationSoundInterval = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_interval") : preferenceFragment.findPreference("pref_meditation_sound_interval"));
prefMeditationSoundInterval.setEntries(meditation_sounds);
prefMeditationSoundInterval.setEntryValues(meditation_sounds_values);
ListPreferenceSound prefMeditationSoundFinish = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_finish") : preferenceFragment.findPreference("pref_meditation_sound_finish"));
prefMeditationSoundFinish.setEntries(meditation_sounds);
prefMeditationSoundFinish.setEntryValues(meditation_sounds_values);
}
void setupPreferences(String pref_type, PreferenceFragment preferenceFragment) {
if (pref_type.equals("all") || pref_type.equals("session")) {
if (preferenceFragment != null) {
sessionPreferenceFragment = (SessionPreferenceFragment) preferenceFragment;
}
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_session_delay") : preferenceFragment.findPreference("pref_session_delay"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_start") : preferenceFragment.findPreference("pref_meditation_sound_start"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_interval") : preferenceFragment.findPreference("pref_meditation_sound_interval"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_session_interval") : preferenceFragment.findPreference("pref_session_interval"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_interval_count") : preferenceFragment.findPreference("pref_interval_count"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_finish") : preferenceFragment.findPreference("pref_meditation_sound_finish"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_notificationcontrol") : preferenceFragment.findPreference("pref_notificationcontrol"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_presetsettings") : preferenceFragment.findPreference("pref_presetsettings"));
}
if (pref_type.equals("all") || pref_type.equals("reminder")) {
if (preferenceFragment != null) {
reminderPreferenceFragment = (ReminderPreferenceFragment) preferenceFragment;
}
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder_text") : preferenceFragment.findPreference("pref_daily_reminder_text"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder_time") : preferenceFragment.findPreference("pref_daily_reminder_time"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder") : preferenceFragment.findPreference("pref_daily_reminder"));
}
if (pref_type.equals("all") || pref_type.equals("meditation")) {
if (preferenceFragment != null) {
meditationPreferenceFragment = (MeditationPreferenceFragment) preferenceFragment;
}
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_usetimepicker") : preferenceFragment.findPreference("pref_usetimepicker"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_text_size") : preferenceFragment.findPreference("pref_text_size"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_progresstab") : preferenceFragment.findPreference("pref_progresstab"));
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_screencontrol") : preferenceFragment.findPreference("pref_screencontrol"));
}
if (pref_type.equals("all") || pref_type.equals("medinet")) {
if (preferenceFragment != null) {
medinetPreferenceFragment = (MediNETPreferenceFragment) preferenceFragment;
}
Preference uploadSessions = (preferenceFragment == null ? findPreference("uploadsessions") : preferenceFragment.findPreference("uploadsessions"));
uploadSessions
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
if (getMeditationAssistant().getMediNETKey().equals("")) {
getMeditationAssistant().getMediNET().askToSignIn();
getMeditationAssistant().shortToast(
getString(R.string.signInToMediNET));
} else {
ArrayList<SessionSQL> sessionssql = getMeditationAssistant().db.getAllLocalSessions();
if (sessionssql.size() == 0) {
getMeditationAssistant().longToast(
getMeditationAssistant().getString(R.string.sessionsNotImported));
return false;
}
if (getMeditationAssistant().getTimestamp()
- uploadsessions_lastlick > 5) {
uploadsessions_lastlick = getMeditationAssistant()
.getTimestamp();
getMeditationAssistant().getMediNET()
.uploadSessions();
}
}
return false;
}
});
Preference importSessions = (preferenceFragment == null ? findPreference("importsessions") : preferenceFragment.findPreference("importsessions"));
importSessions
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
if (getMeditationAssistant().getMediNETKey().equals("")) {
getMeditationAssistant().getMediNET().askToSignIn();
getMeditationAssistant().shortToast(
getString(R.string.signInToImport));
} else {
if (getMeditationAssistant().getTimestamp()
- importsessions_lastlick > 5) {
importsessions_lastlick = getMeditationAssistant()
.getTimestamp();
getMeditationAssistant().getMediNET()
.syncSessions();
}
}
return false;
}
});
}
if (pref_type.equals("all") || pref_type.equals("miscellaneous")) {
if (preferenceFragment != null) {
miscellaneousPreferenceFragment = (MiscellaneousPreferenceFragment) preferenceFragment;
}
bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_theme") : preferenceFragment.findPreference("pref_theme"));
}
}
/**
* Shows the simplified settings UI if the device configuration if the
* device configuration dictates that a simplified, single-pane UI should be
* shown.
*/
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
// In the simplified UI, fragments are not used at all and we instead
// use the older PreferenceActivity APIs.
// Add 'Session' preferences.
PreferenceCategory fakeHeader = new PreferenceCategory(this);
addPreferencesFromResource(R.xml.pref_session);
// Add 'Daily Reminder' preferences
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_daily_reminder);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_reminder);
// Add 'Meditation' preferences
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.meditation);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_meditation);
// Add 'MediNET' preferences
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.mediNET);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_medinet);
// Add 'Miscellaneous' preferences
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.miscellaneous);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_miscellaneous);
setupSoundPreferences(null);
setupPreferences("all", null);
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
private String customSoundSummary(String meditation_sound) {
if (meditation_sound == null || meditation_sound.equals("")) {
return getString(R.string.noSound);
}
try {
return meditation_sound.substring(meditation_sound.lastIndexOf("/") + 1);
} catch (Exception e) {
return meditation_sound;
}
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
if (preference.getKey().equals("pref_daily_reminder") || preference.getKey().equals("pref_usetimepicker")) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
getMeditationAssistant().getPrefs()
.getBoolean(preference.getKey(), false)
);
} else if (preference.getKey().equals("pref_presetsettings")) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, getMeditationAssistant().getPrefs().getStringSet("pref_presetsettings", new HashSet<String>(Arrays.asList(getResources().getStringArray(R.array.presetsettings_default))))
);
} else {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
getMeditationAssistant().getPrefs()
.getString(preference.getKey(), "")
);
}
}
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) this.getApplication();
}
return ma;
}
@Override
protected boolean isValidFragment(String fragmentName) {
return SessionPreferenceFragment.class.getName().equals(fragmentName) ||
ReminderPreferenceFragment.class.getName().equals(fragmentName) ||
MeditationPreferenceFragment.class.getName().equals(fragmentName) ||
MediNETPreferenceFragment.class.getName().equals(fragmentName) ||
MiscellaneousPreferenceFragment.class.getName().equals(fragmentName);
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class SessionPreferenceFragment extends PreferenceFragment {
public SessionPreferenceFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_session);
PreferenceCategory prefCatSession = (PreferenceCategory) findPreference("pref_cat_session");
getPreferenceScreen().removePreference(prefCatSession);
SettingsActivity settingsactivity = (SettingsActivity) getActivity();
settingsactivity.setupSoundPreferences(this);
settingsactivity.setupPreferences("session", this);
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ReminderPreferenceFragment extends PreferenceFragment {
public ReminderPreferenceFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_reminder);
SettingsActivity settingsactivity = (SettingsActivity) getActivity();
settingsactivity.setupPreferences("reminder", this);
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class MeditationPreferenceFragment extends PreferenceFragment {
public MeditationPreferenceFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_meditation);
SettingsActivity settingsactivity = (SettingsActivity) getActivity();
settingsactivity.setupPreferences("meditation", this);
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class MediNETPreferenceFragment extends PreferenceFragment {
public MediNETPreferenceFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_medinet);
SettingsActivity settingsactivity = (SettingsActivity) getActivity();
settingsactivity.setupPreferences("medinet", this);
}
}
/**
* This fragment shows data and sync preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class MiscellaneousPreferenceFragment extends PreferenceFragment {
public MiscellaneousPreferenceFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_miscellaneous);
SettingsActivity settingsactivity = (SettingsActivity) getActivity();
settingsactivity.setupPreferences("miscellaneous", this);
}
}
}

View File

@ -0,0 +1,149 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.NumberFormat;
import java.util.Locale;
public class StatsFragment extends Fragment {
private MeditationAssistant ma = null;
private View fragment_progress_stats = null;
SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("sessionsupdate")) {
Log.d("MeditationAssistant", "Got sessions update, refreshing StatsFragment");
refreshStatsDisplay();
}
}
};
public MeditationAssistant getMeditationAssistant() {
if (ma == null) {
ma = (MeditationAssistant) getActivity().getApplication();
}
return ma;
}
public void refreshStatsDisplay() {
if (fragment_progress_stats == null) {
return;
}
Locale currentLocale = getResources().getConfiguration().locale;
int time_spent_meditating = getMeditationAssistant().db.getTotalTimeSpentMeditating();
int time_spent_meditating_days = time_spent_meditating / 86400;
int abovedays = time_spent_meditating % 86400;
int time_spent_meditating_hours = abovedays / 3600;
int abovehours = abovedays % 3600;
int time_spent_meditating_minutes = abovehours / 60;
TextView txtTimespentMeditatingDays = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingDays);
TextView txtTimespentMeditatingHours = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingHours);
TextView txtTimespentMeditatingMinutes = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingMinutes);
txtTimespentMeditatingDays.setText(String.valueOf(time_spent_meditating_days));
txtTimespentMeditatingHours.setText(String.valueOf(time_spent_meditating_hours));
txtTimespentMeditatingMinutes.setText(String.valueOf(time_spent_meditating_minutes));
TextView txtOtherStatisticsSessions = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsSessions);
TextView txtOtherStatisticsLongestDuration = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsLongestDuration);
TextView txtOtherStatisticsAverageDuration = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsAverageDuration);
TextView txtOtherStatisticsLongestStreak = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsLongestStreak);
int numSessions = getMeditationAssistant().db.getNumSessions();
txtOtherStatisticsSessions.setText(NumberFormat.getNumberInstance(currentLocale).format(numSessions));
double secondsPerSession = 0;
if (numSessions > 0) {
secondsPerSession = time_spent_meditating / numSessions;
secondsPerSession = Math.floor(secondsPerSession);
}
int secondsPerSessionHours = (int) secondsPerSession / 3600;
int secondsPerSessionRemainder = (int) secondsPerSession % 3600;
int secondsPerSessionMinutes = secondsPerSessionRemainder / 60;
int secondsPerSessionSeconds = secondsPerSessionRemainder % 60;
txtOtherStatisticsAverageDuration.setText(String.valueOf(secondsPerSessionHours) + ":" + String.format("%02d", secondsPerSessionMinutes) + ":" + String.format("%02d", secondsPerSessionSeconds));
// Re-use variables
secondsPerSession = getMeditationAssistant().db.getLongestSessionLength();
secondsPerSessionHours = (int) secondsPerSession / 3600;
secondsPerSessionRemainder = (int) secondsPerSession % 3600;
secondsPerSessionMinutes = secondsPerSessionRemainder / 60;
secondsPerSessionSeconds = secondsPerSessionRemainder % 60;
txtOtherStatisticsLongestDuration.setText(String.valueOf(secondsPerSessionHours) + ":" + String.format("%02d", secondsPerSessionMinutes) + ":" + String.format("%02d", secondsPerSessionSeconds));
int longestStreak = getMeditationAssistant().getLongestMeditationStreak();
txtOtherStatisticsLongestStreak.setText(String.format(getResources().getQuantityString(R.plurals.daysOfMeditationMinimal, longestStreak, longestStreak), NumberFormat.getNumberInstance(currentLocale).format(longestStreak)));
}
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
int color_primary = getResources().getColor(getMeditationAssistant().getMATextColor(true));
int color_primary_disabled = getResources().getColor(getMeditationAssistant().getMATextColor(false));
/* Getting resource not found errors here */
try {
color_primary = getResources().getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant().getMATheme(),
new int[]{android.R.attr.textColorPrimary})
.getResourceId(0, 0)
);
color_primary_disabled = getResources()
.getColor(
getMeditationAssistant()
.getTheme()
.obtainStyledAttributes(
getMeditationAssistant()
.getMATheme(),
new int[]{android.R.attr.textColorPrimaryDisableOnly}
)
.getResourceId(0, 0)
);
} catch (Exception e) {
Log.d("MeditationAssistant", "Unable to get color resources in StatsFragment:");
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Context ctx = getActivity().getApplicationContext();
fragment_progress_stats = inflater.inflate(R.layout.fragment_progress_stats, null);
refreshStatsDisplay();
return fragment_progress_stats;
}
@Override
public void onPause() {
getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onPause();
}
@Override
public void onResume() {
getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
super.onResume();
}
}

View File

@ -0,0 +1,551 @@
package sh.ftp.rocketninelabs.meditationassistant;
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed 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.
*/
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Locale;
/**
* A view for selecting the time of day, in either 24 hour or AM/PM mode. The
* hour, each minute digit, and AM/PM (if applicable) can be conrolled by
* vertical spinners. The hour can be entered by keyboard input. Entering in two
* digit hours can be accomplished by hitting two digits within a timeout of
* about a second (e.g. '1' then '2' to select 12). The minutes can be entered
* by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p'
* or 'P' to pick. For a dialog using this view, see
* {@link android.app.TimePickerDialog}.
* <p>
* See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
* guide.
* </p>
*/
//@Widget
public class TimePicker extends FrameLayout {
private static final boolean DEFAULT_ENABLED_STATE = true;
private static final int HOURS_IN_HALF_DAY = 12;
/**
* A no-op callback used in the constructor to avoid null checks later in
* the code.
*/
private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() {
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
}
};
// ui components
public final NumberPicker mHourSpinner;
private final NumberPicker mMinuteSpinner;
private final NumberPicker mAmPmSpinner;
private final EditText mHourSpinnerInput;
private final EditText mMinuteSpinnerInput;
private final EditText mAmPmSpinnerInput;
private final TextView mDivider;
// Note that the legacy implementation of the TimePicker is
// using a button for toggling between AM/PM while the new
// version uses a NumberPicker spinner. Therefore the code
// accommodates these two cases to be backwards compatible.
private final Button mAmPmButton;
private final String[] mAmPmStrings;
// state
private boolean mIs24HourView;
private boolean mIsAm;
private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
// callbacks
private OnTimeChangedListener mOnTimeChangedListener;
private Calendar mTempCalendar;
private Locale mCurrentLocale;
public TimePicker(Context context) {
this(context, null);
}
public TimePicker(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.timePickerStyle);
}
public TimePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// initialization based on locale
setCurrentLocale(Locale.getDefault());
// process style attributes
//TypedArray attributesArray = context.obtainStyledAttributes(
// attrs, R.styleable.TimePicker, defStyle, 0);
//int layoutResourceId = attributesArray.getResourceId(
// R.styleable.TimePicker_internalLayout, R.layout.time_picker);
//attributesArray.recycle();
int layoutResourceId = R.layout.time_picker_holo;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(layoutResourceId, TimePicker.this, true);
// hour
mHourSpinner = (NumberPicker) findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
if (!is24HourView()) {
if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY)
|| (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) {
mIsAm = !mIsAm;
updateAmPmControl();
}
}
onTimeChanged();
}
});
mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.np__numberpicker_input);
mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// divider (only for the new widget style)
mDivider = (TextView) findViewById(R.id.divider);
if (mDivider != null) {
mDivider.setText(R.string.time_picker_separator);
}
// minute
mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
int minValue = mMinuteSpinner.getMinValue();
int maxValue = mMinuteSpinner.getMaxValue();
if (oldVal == maxValue && newVal == minValue) {
int newHour = mHourSpinner.getValue() + 1;
if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) {
mIsAm = !mIsAm;
updateAmPmControl();
}
mHourSpinner.setValue(newHour);
} else if (oldVal == minValue && newVal == maxValue) {
int newHour = mHourSpinner.getValue() - 1;
if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) {
mIsAm = !mIsAm;
updateAmPmControl();
}
mHourSpinner.setValue(newHour);
}
onTimeChanged();
}
});
mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.np__numberpicker_input);
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
/* Get the localized am/pm strings and use them in the spinner */
mAmPmStrings = new DateFormatSymbols().getAmPmStrings();
// am/pm
View amPmView = findViewById(R.id.amPm);
if (amPmView instanceof Button) {
mAmPmSpinner = null;
mAmPmSpinnerInput = null;
mAmPmButton = (Button) amPmView;
mAmPmButton.setOnClickListener(new OnClickListener() {
public void onClick(View button) {
button.requestFocus();
mIsAm = !mIsAm;
updateAmPmControl();
onTimeChanged();
}
});
} else {
mAmPmButton = null;
mAmPmSpinner = (NumberPicker) amPmView;
mAmPmSpinner.setMinValue(0);
mAmPmSpinner.setMaxValue(1);
mAmPmSpinner.setDisplayedValues(mAmPmStrings);
mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
updateInputState();
picker.requestFocus();
mIsAm = !mIsAm;
updateAmPmControl();
onTimeChanged();
}
});
mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.np__numberpicker_input);
mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
}
// update controls to initial state
updateHourControl();
updateAmPmControl();
setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
// set to current time
setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
if (!isEnabled()) {
setEnabled(false);
}
// If not explicitly specified this view is important for accessibility.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
}
@Override
public boolean isEnabled() {
return mIsEnabled;
}
@Override
public void setEnabled(boolean enabled) {
if (mIsEnabled == enabled) {
return;
}
super.setEnabled(enabled);
mMinuteSpinner.setEnabled(enabled);
if (mDivider != null) {
mDivider.setEnabled(enabled);
}
mHourSpinner.setEnabled(enabled);
if (mAmPmSpinner != null) {
mAmPmSpinner.setEnabled(enabled);
} else {
mAmPmButton.setEnabled(enabled);
}
mIsEnabled = enabled;
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setCurrentLocale(newConfig.locale);
}
/**
* Sets the current locale.
*
* @param locale The current locale.
*/
private void setCurrentLocale(Locale locale) {
if (locale.equals(mCurrentLocale)) {
return;
}
mCurrentLocale = locale;
mTempCalendar = Calendar.getInstance(locale);
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState, getCurrentHour(), getCurrentMinute());
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setCurrentHour(ss.getHour());
setCurrentMinute(ss.getMinute());
}
/**
* Set the callback that indicates the time has been adjusted by the user.
*
* @param onTimeChangedListener the callback, should not be null.
*/
public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
mOnTimeChangedListener = onTimeChangedListener;
}
/**
* @return The current hour in the range (0-23).
*/
public Integer getCurrentHour() {
int currentHour = mHourSpinner.getValue();
if (is24HourView()) {
return currentHour;
} else if (mIsAm) {
return currentHour % HOURS_IN_HALF_DAY;
} else {
return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
}
}
/**
* Set the current hour.
*/
public void setCurrentHour(Integer currentHour) {
// why was Integer used in the first place?
if (currentHour == null || currentHour == getCurrentHour()) {
return;
}
if (!is24HourView()) {
// convert [0,23] ordinal to wall clock display
if (currentHour >= HOURS_IN_HALF_DAY) {
mIsAm = false;
if (currentHour > HOURS_IN_HALF_DAY) {
currentHour = currentHour - HOURS_IN_HALF_DAY;
}
} else {
mIsAm = true;
if (currentHour == 0) {
currentHour = HOURS_IN_HALF_DAY;
}
}
updateAmPmControl();
}
mHourSpinner.setValue(currentHour);
onTimeChanged();
}
/**
* Set whether in 24 hour or AM/PM mode.
*
* @param is24HourView True = 24 hour mode. False = AM/PM.
*/
public void setIs24HourView(Boolean is24HourView) {
if (mIs24HourView == is24HourView) {
return;
}
mIs24HourView = is24HourView;
// cache the current hour since spinner range changes
int currentHour = getCurrentHour();
updateHourControl();
// set value after spinner range is updated
setCurrentHour(currentHour);
updateAmPmControl();
}
/**
* @return true if this is in 24 hour view else false.
*/
public boolean is24HourView() {
return mIs24HourView;
}
/**
* @return The current minute.
*/
public Integer getCurrentMinute() {
return mMinuteSpinner.getValue();
}
/**
* Set the current minute (0-59).
*/
public void setCurrentMinute(Integer currentMinute) {
if (currentMinute == getCurrentMinute()) {
return;
}
mMinuteSpinner.setValue(currentMinute);
onTimeChanged();
}
@Override
public int getBaseline() {
return mHourSpinner.getBaseline();
}
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
onPopulateAccessibilityEvent(event);
return true;
}
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
int flags = DateUtils.FORMAT_SHOW_TIME;
if (mIs24HourView) {
flags |= DateUtils.FORMAT_24HOUR;
} else {
flags |= DateUtils.FORMAT_12HOUR;
}
mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour());
mTempCalendar.set(Calendar.MINUTE, getCurrentMinute());
String selectedDateUtterance = DateUtils.formatDateTime(getContext(),
mTempCalendar.getTimeInMillis(), flags);
event.getText().add(selectedDateUtterance);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(TimePicker.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(TimePicker.class.getName());
}
private void updateHourControl() {
if (is24HourView()) {
mHourSpinner.setMinValue(0);
mHourSpinner.setMaxValue(23);
mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
} else {
mHourSpinner.setMinValue(1);
mHourSpinner.setMaxValue(12);
mHourSpinner.setFormatter(null);
}
}
private void updateAmPmControl() {
if (is24HourView()) {
if (mAmPmSpinner != null) {
mAmPmSpinner.setVisibility(View.GONE);
} else {
mAmPmButton.setVisibility(View.GONE);
}
} else {
int index = mIsAm ? Calendar.AM : Calendar.PM;
if (mAmPmSpinner != null) {
mAmPmSpinner.setValue(index);
mAmPmSpinner.setVisibility(View.VISIBLE);
} else {
mAmPmButton.setText(mAmPmStrings[index]);
mAmPmButton.setVisibility(View.VISIBLE);
}
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
private void onTimeChanged() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
if (mOnTimeChangedListener != null) {
mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute());
}
}
private void trySetContentDescription(View root, int viewId, int contDescResId) {
View target = root.findViewById(viewId);
if (target != null) {
target.setContentDescription(getContext().getString(contDescResId));
}
}
private void updateInputState() {
// Make sure that if the user changes the value and the IME is active
// for one of the inputs if this widget, the IME is closed. If the user
// changed the value via the IME and there is a next input the IME will
// be shown, otherwise the user chose another means of changing the
// value and having the IME up makes no sense.
//InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
InputMethodManager inputMethodManager =
(InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
if (inputMethodManager.isActive(mHourSpinnerInput)) {
mHourSpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
} else if (inputMethodManager.isActive(mMinuteSpinnerInput)) {
mMinuteSpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
} else if (inputMethodManager.isActive(mAmPmSpinnerInput)) {
mAmPmSpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
}
}
}
/**
* The callback interface used to indicate the time has been adjusted.
*/
public interface OnTimeChangedListener {
/**
* @param view The view associated with this listener.
* @param hourOfDay The current hour.
* @param minute The current minute.
*/
void onTimeChanged(TimePicker view, int hourOfDay, int minute);
}
/**
* Used to save / restore state of time picker
*/
private static class SavedState extends BaseSavedState {
@SuppressWarnings({"unused", "hiding"})
public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private final int mHour;
private final int mMinute;
private SavedState(Parcelable superState, int hour, int minute) {
super(superState);
mHour = hour;
mMinute = minute;
}
private SavedState(Parcel in) {
super(in);
mHour = in.readInt();
mMinute = in.readInt();
}
public int getHour() {
return mHour;
}
public int getMinute() {
return mMinute;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mHour);
dest.writeInt(mMinute);
}
}
}

View File

@ -0,0 +1,157 @@
package sh.ftp.rocketninelabs.meditationassistant;
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed 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.
*/
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import sh.ftp.rocketninelabs.meditationassistant.TimePicker.OnTimeChangedListener;
/**
* A dialog that prompts the user for the time of day using a {@link TimePicker}.
* <p/>
* <p>See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
* guide.</p>
*/
public class TimePickerDialog extends AlertDialog
implements OnClickListener, OnTimeChangedListener {
private static final String HOUR = "hour";
private static final String MINUTE = "minute";
private static final String IS_24_HOUR = "is24hour";
private final TimePicker mTimePicker;
private final OnTimeSetListener mCallback;
int mInitialHourOfDay;
int mInitialMinute;
boolean mIs24HourView;
/**
* @param context Parent.
* @param callBack How parent is notified.
* @param hourOfDay The initial hour.
* @param minute The initial minute.
* @param is24HourView Whether this is a 24 hour view, or AM/PM.
*/
public TimePickerDialog(Context context,
OnTimeSetListener callBack,
int hourOfDay, int minute, boolean is24HourView) {
this(context, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? R.style.Theme_Dialog_Alert : 0, callBack, hourOfDay, minute, is24HourView);
}
/**
* @param context Parent.
* @param theme the theme to apply to this dialog
* @param callBack How parent is notified.
* @param hourOfDay The initial hour.
* @param minute The initial minute.
* @param is24HourView Whether this is a 24 hour view, or AM/PM.
*/
public TimePickerDialog(Context context,
int theme,
OnTimeSetListener callBack,
int hourOfDay, int minute, boolean is24HourView) {
super(context, theme);
mCallback = callBack;
mInitialHourOfDay = hourOfDay;
mInitialMinute = minute;
mIs24HourView = is24HourView;
setIcon(0);
setTitle(R.string.setTime);
Context themeContext = getContext();
setButton(BUTTON_POSITIVE, themeContext.getText(R.string.set), this);
LayoutInflater inflater =
(LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.time_picker_dialog, null);
setView(view);
mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
// initialize state
mTimePicker.setIs24HourView(mIs24HourView);
mTimePicker.setCurrentHour(mInitialHourOfDay);
mTimePicker.setCurrentMinute(mInitialMinute);
mTimePicker.setOnTimeChangedListener(this);
}
public void onClick(DialogInterface dialog, int which) {
tryNotifyTimeSet();
}
public void updateTime(int hourOfDay, int minutOfHour) {
mTimePicker.setCurrentHour(hourOfDay);
mTimePicker.setCurrentMinute(minutOfHour);
}
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
/* do nothing */
}
private void tryNotifyTimeSet() {
if (mCallback != null) {
mTimePicker.clearFocus();
mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute());
}
}
@Override
protected void onStop() {
tryNotifyTimeSet();
super.onStop();
}
@Override
public Bundle onSaveInstanceState() {
Bundle state = super.onSaveInstanceState();
state.putInt(HOUR, mTimePicker.getCurrentHour());
state.putInt(MINUTE, mTimePicker.getCurrentMinute());
state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
return state;
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int hour = savedInstanceState.getInt(HOUR);
int minute = savedInstanceState.getInt(MINUTE);
mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
mTimePicker.setCurrentHour(hour);
mTimePicker.setCurrentMinute(minute);
}
/**
* The callback interface used to indicate the user is done filling in
* the time (they clicked on the 'Set' button).
*/
public interface OnTimeSetListener {
/**
* @param view The view associated with this listener.
* @param hourOfDay The hour that was set.
* @param minute The minute that was set.
*/
void onTimeSet(TimePicker view, int hourOfDay, int minute);
}
}

View File

@ -0,0 +1,114 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class TimePreference extends DialogPreference {
private int lastHour = 0;
private int lastMinute = 0;
private TimePicker picker = null;
private Boolean is24hour = true;
private Integer maxhours = 24;
private Context ctx = null;
public TimePreference(Context context, AttributeSet attrs) {
super(context, attrs);
ctx = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePreference);
is24hour = a.getBoolean(R.styleable.TimePreference_is24hour, false);
maxhours = a.getInteger(R.styleable.TimePreference_maxHours, 24);
a.recycle();
setPositiveButtonText("Set");
setNegativeButtonText("Cancel");
}
public static int getHour(String time) {
String[] pieces = time.split(":");
return (Integer.parseInt(pieces[0]));
}
public static int getMinute(String time) {
String[] pieces = time.split(":");
return (Integer.parseInt(pieces[1]));
}
@Override
protected View onCreateDialogView() {
picker = new TimePicker(getContext());
picker.setIs24HourView(is24hour);
if (maxhours != 24) {
picker.mHourSpinner.setMaxValue(maxhours);
}
return (picker);
}
@Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
picker.setCurrentHour(lastHour);
picker.setCurrentMinute(lastMinute);
Log.d("MeditationAssistant", "TimePreference onBindDialogView: " + String.valueOf(lastHour) + ":" + String.valueOf(lastMinute));
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
lastHour = picker.getCurrentHour();
lastMinute = picker.getCurrentMinute();
String time = String.valueOf(lastHour) + ":" + String.valueOf(lastMinute);
Log.d("MeditationAssistant", "TimePreference positive result: " + time);
if (callChangeListener(time)) {
persistString(time);
}
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return (a.getString(index));
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
String time = null;
String defaultv = "00:00";
if (restoreValue) {
if (defaultValue == null) {
time = getPersistedString(defaultv);
} else {
time = getPersistedString(defaultValue.toString());
}
} else {
time = defaultValue.toString();
}
/*if (getKey() != null) {
time = PreferenceManager.getDefaultSharedPreferences(ctx).getString(getKey(), getKey().equals("pref_session_delay") ? "00:15" : (getKey().equals("pref_daily_reminder") ? "19:00" : "00:00"));
}*/
Log.d("MeditationAssistant", String.valueOf(getKey()) + " current value - " + PreferenceManager.getDefaultSharedPreferences(ctx).getString(getKey(), ""));
Log.d("MeditationAssistant", "TimePreference (" + String.valueOf(getKey()) + ") restoreValue: " + String.valueOf(restoreValue) + " - defaultValue: " + String.valueOf(defaultValue) + " - defaultv: " + String.valueOf(defaultv) + " - time: " + String.valueOf(time));
lastHour = getHour(time);
lastMinute = getMinute(time);
}
}

View File

@ -0,0 +1,36 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.content.Context;
import android.os.PowerManager;
import android.util.Log;
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context ctx, Boolean turnScreenOn) {
Log.d("MeditationAssistant", "WAKELOCKER: Acquiring wakelock");
if (wakeLock != null) {
Log.d("MeditationAssistant", "WAKELOCKER: Releasing old wakelock first...");
wakeLock.release();
}
PowerManager pm = (PowerManager) ctx
.getSystemService(Context.POWER_SERVICE);
if (turnScreenOn) {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK |
PowerManager.ON_AFTER_RELEASE, "MeditationAssistant");
} else {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MeditationAssistant");
}
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) {
Log.d("MeditationAssistant", "WAKELOCKER: Releasing wakelock");
wakeLock.release();
}
wakeLock = null;
}
}

View File

@ -0,0 +1,55 @@
package sh.ftp.rocketninelabs.meditationassistant;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class WearListenerService extends WearableListenerService {
private static final String TAG = "MeditationAssistant";
private static final String START_ACTIVITY_PATH = "/start-activity";
private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onDataChanged: " + dataEvents);
}
final List events = FreezableUtils
.freezeIterable(dataEvents);
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
ConnectionResult connectionResult =
googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
if (!connectionResult.isSuccess()) {
Log.e(TAG, "Failed to connect to GoogleApiClient.");
}
// Loop through the events and send a message
// to the node that created the data item.
/*for (DataEvent event : events) {
Uri uri = event.getDataItem().getUri();
// Get the node id from the host value of the URI
String nodeId = uri.getHost();
// Set the data of the message to be the bytes of the URI
byte[] payload = uri.toString().getBytes();
// Send the RPC
Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
DATA_ITEM_RECEIVED_PATH, payload);
}*/
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="220"
android:fromAlpha="0.0"
android:interpolator="@android:anim/decelerate_interpolator"
android:repeatCount="0"
android:toAlpha="1.0" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="220"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatCount="0"
android:toAlpha="0.0" />
</set>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="777"
android:fromDegrees="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:startOffset="0"
android:toDegrees="359" />
<rotate
android:duration="500"
android:fromDegrees="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:startOffset="0"
android:toDegrees="180" />
<rotate
android:duration="575"
android:fromDegrees="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:startOffset="0"
android:toDegrees="-144" />
<scale
android:duration="450"
android:fillBefore="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatCount="infinite"
android:toXScale="1.0"
android:toYScale="1.0" />
<translate
android:duration="700"
android:fromXDelta="-200"
android:fromYDelta="-200"
android:interpolator="@android:anim/accelerate_interpolator" />
<translate
android:duration="4000"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="200"
android:toYDelta="200" />
<translate
android:duration="818"
android:fromXDelta="-30"
android:fromYDelta="2121"
android:interpolator="@android:anim/accelerate_interpolator" />
<translate
android:duration="2214"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="414"
android:toYDelta="177" />
<scale
android:duration="3777"
android:fillBefore="false"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatCount="infinite"
android:toXScale="0.0"
android:toYScale="0.0" />
</set>

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Some files were not shown because too many files have changed in this diff Show More