diff --git a/Android/Warpzone Status Widget/.classpath b/Android/Warpzone Status Widget/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..7bc01d9a9c6873b7e4fea3b29ee945267845ae86 --- /dev/null +++ b/Android/Warpzone Status Widget/.classpath @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/Android/Warpzone Status Widget/.project b/Android/Warpzone Status Widget/.project new file mode 100644 index 0000000000000000000000000000000000000000..623f755918cf1a22422408f2506ce266b1fba4ac --- /dev/null +++ b/Android/Warpzone Status Widget/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>Warpzone Status Widget</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/Android/Warpzone Status Widget/.settings/org.eclipse.jdt.core.prefs b/Android/Warpzone Status Widget/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..b080d2ddc88fb0b4d7c93cd4d361c775525b4dbb --- /dev/null +++ b/Android/Warpzone Status Widget/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/Android/Warpzone Status Widget/AndroidManifest.xml b/Android/Warpzone Status Widget/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e930f599c046589285448508fee024825afd9d2a --- /dev/null +++ b/Android/Warpzone Status Widget/AndroidManifest.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="ms.warpzone.warpzonestatuswidget" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="8" + android:targetSdkVersion="17" /> + + <uses-permission + android:name="android.permission.INTERNET" /> + + <uses-permission + android:name="android.permission.VIBRATE" /> + + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name="ms.warpzone.warpzonestatuswidget.SettingsActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> + </intent-filter> + </activity> + <receiver android:name="ms.warpzone.warpzonestatuswidget.WidgetProvider" > + <intent-filter > + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + </intent-filter> + <meta-data + android:name="android.appwidget.provider" + android:resource="@xml/widget_provider" /> + </receiver> + </application> + +</manifest> diff --git a/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/BuildConfig.java b/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/BuildConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..59f4c2d6b1ddbc2de602c7607e1ab1f77b5256ec --- /dev/null +++ b/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package ms.warpzone.warpzonestatuswidget; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/R.java b/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/R.java new file mode 100644 index 0000000000000000000000000000000000000000..70ba3cb6874c760ce908d285b9fe4ef5ae5673bd --- /dev/null +++ b/Android/Warpzone Status Widget/gen/ms/warpzone/warpzonestatuswidget/R.java @@ -0,0 +1,82 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package ms.warpzone.warpzonestatuswidget; + +public final class R { + public static final class array { + public static final int pref_sync_frequency_titles=0x7f060000; + public static final int pref_sync_frequency_values=0x7f060001; + } + public static final class attr { + } + public static final class drawable { + public static final int border=0x7f020000; + public static final int ic_launcher=0x7f020001; + public static final int warpzone_logo_green_small=0x7f020002; + public static final int warpzone_logo_orange_small=0x7f020003; + public static final int warpzone_logo_red_small=0x7f020004; + public static final int warpzone_logo_small=0x7f020005; + } + public static final class id { + public static final int imageView=0x7f080000; + } + public static final class layout { + public static final int widget_layout=0x7f030000; + } + public static final class string { + public static final int app_name=0x7f050000; + public static final int pref_button_done=0x7f050009; + /** Strings related to Settings + Example settings for Data & Sync + */ + public static final int pref_header_data_sync=0x7f050001; + /** Example settings for Notifications + */ + public static final int pref_header_notifications=0x7f050004; + public static final int pref_ringtone_silent=0x7f050007; + public static final int pref_title_ringtone=0x7f050006; + public static final int pref_title_status_change_notifications=0x7f050005; + public static final int pref_title_sync_frequency=0x7f050002; + public static final int pref_title_system_sync_settings=0x7f050003; + public static final int pref_title_vibrate=0x7f050008; + } + public static final class style { + /** + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + + + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + + + Base application theme for API 11+. This theme completely replaces + AppBaseTheme from res/values/styles.xml on API 11+ devices. + + API 11 theme customizations can go here. + + Base application theme for API 14+. This theme completely replaces + AppBaseTheme from BOTH res/values/styles.xml and + res/values-v11/styles.xml on API 14+ devices. + + API 14 theme customizations can go here. + */ + public static final int AppBaseTheme=0x7f070000; + /** Application theme. + All customizations that are NOT specific to a particular API-level can go here. + */ + public static final int AppTheme=0x7f070001; + } + public static final class xml { + public static final int pref_data_sync=0x7f040000; + public static final int pref_headers=0x7f040001; + public static final int pref_notification=0x7f040002; + public static final int widget_provider=0x7f040003; + } +} diff --git a/Android/Warpzone Status Widget/ic_launcher-web.png b/Android/Warpzone Status Widget/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..f78fe2633ec252e7b24f04d07b24ac121de034a2 Binary files /dev/null and b/Android/Warpzone Status Widget/ic_launcher-web.png differ diff --git a/Android/Warpzone Status Widget/libs/android-support-v4.jar b/Android/Warpzone Status Widget/libs/android-support-v4.jar new file mode 100644 index 0000000000000000000000000000000000000000..6080877d4ade158f24ad7ccd9a10db2ac9060b47 Binary files /dev/null and b/Android/Warpzone Status Widget/libs/android-support-v4.jar differ diff --git a/Android/Warpzone Status Widget/proguard-project.txt b/Android/Warpzone Status Widget/proguard-project.txt new file mode 100644 index 0000000000000000000000000000000000000000..f2fe1559a217865a5454add526dcc446f892385b --- /dev/null +++ b/Android/Warpzone Status Widget/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/Android/Warpzone Status Widget/project.properties b/Android/Warpzone Status Widget/project.properties new file mode 100644 index 0000000000000000000000000000000000000000..a3ee5ab64f5e1901414e83e26717725e035b2aae --- /dev/null +++ b/Android/Warpzone Status Widget/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-17 diff --git a/Android/Warpzone Status Widget/res/drawable-hdpi/ic_launcher.png b/Android/Warpzone Status Widget/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e76c6f76ea816210ebcafc951b00b89b43c9a502 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-hdpi/ic_launcher.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_green_small.png b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_green_small.png new file mode 100644 index 0000000000000000000000000000000000000000..f502ab7c856319b2998909075ad05726632c1556 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_green_small.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_orange_small.png b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_orange_small.png new file mode 100644 index 0000000000000000000000000000000000000000..1e03985844dad8809046fda930e423891ea26753 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_orange_small.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_red_small.png b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_red_small.png new file mode 100644 index 0000000000000000000000000000000000000000..18d79efc4ea6bde3d10032da6807e1121ab38def Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_red_small.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_small.png b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..313c660de78a42f744e31e1829c0dbe8b30f6cef Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-hdpi/warpzone_logo_small.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-ldpi/ic_launcher.png b/Android/Warpzone Status Widget/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..badb752e7d4622585b3cb9f5dffb9bde50312651 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-ldpi/ic_launcher.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-mdpi/ic_launcher.png b/Android/Warpzone Status Widget/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7fac9b71d058443388f06e9b463461c6005a36 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-mdpi/ic_launcher.png differ diff --git a/Android/Warpzone Status Widget/res/drawable-xhdpi/ic_launcher.png b/Android/Warpzone Status Widget/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0888d5262c669f52b2d2129406b45116d09247e6 Binary files /dev/null and b/Android/Warpzone Status Widget/res/drawable-xhdpi/ic_launcher.png differ diff --git a/Android/Warpzone Status Widget/res/drawable/border.xml b/Android/Warpzone Status Widget/res/drawable/border.xml new file mode 100644 index 0000000000000000000000000000000000000000..12021f87d9ecc9d26914146a97c26d23492b7a7b --- /dev/null +++ b/Android/Warpzone Status Widget/res/drawable/border.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#77000000" /> + <stroke android:width="1dp" android:color="#77999999" /> + <padding android:left="4dp" android:top="4dp" android:right="4dp" android:bottom="4dp" /> + <corners android:radius="64dp" android:topRightRadius="20dp" /> +</shape> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/layout/widget_layout.xml b/Android/Warpzone Status Widget/res/layout/widget_layout.xml new file mode 100644 index 0000000000000000000000000000000000000000..5b60f261d6a344156a21a9ef54fb4e5c443c6f0e --- /dev/null +++ b/Android/Warpzone Status Widget/res/layout/widget_layout.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="63dp" + android:layout_height="63dp" + android:orientation="vertical" + android:background="@drawable/border"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="55.5dp" + android:layout_height="55.5dp" + android:src="@drawable/warpzone_logo_orange_small" /> + +</LinearLayout> diff --git a/Android/Warpzone Status Widget/res/values-v11/styles.xml b/Android/Warpzone Status Widget/res/values-v11/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..541752f6edf47a27cad70a23c00cc17aa4c84c08 --- /dev/null +++ b/Android/Warpzone Status Widget/res/values-v11/styles.xml @@ -0,0 +1,11 @@ +<resources> + + <!-- + Base application theme for API 11+. This theme completely replaces + AppBaseTheme from res/values/styles.xml on API 11+ devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Holo.Light"> + <!-- API 11 theme customizations can go here. --> + </style> + +</resources> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/values-v14/styles.xml b/Android/Warpzone Status Widget/res/values-v14/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..f20e01501dfde7d1f4cc9c29f85169ce57bc5846 --- /dev/null +++ b/Android/Warpzone Status Widget/res/values-v14/styles.xml @@ -0,0 +1,12 @@ +<resources> + + <!-- + Base application theme for API 14+. This theme completely replaces + AppBaseTheme from BOTH res/values/styles.xml and + res/values-v11/styles.xml on API 14+ devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar"> + <!-- API 14 theme customizations can go here. --> + </style> + +</resources> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/values/strings.xml b/Android/Warpzone Status Widget/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..8731b340430e4aa88f443427bcb89d7335ad481e --- /dev/null +++ b/Android/Warpzone Status Widget/res/values/strings.xml @@ -0,0 +1,5 @@ +<resources> + + <string name="app_name">Warpzone Status Widget</string> + +</resources> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/values/strings_activity_settings.xml b/Android/Warpzone Status Widget/res/values/strings_activity_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..c582e7e555715f58db0ee132cad18e4db4ff7870 --- /dev/null +++ b/Android/Warpzone Status Widget/res/values/strings_activity_settings.xml @@ -0,0 +1,41 @@ +<resources> + + <!-- Strings related to Settings --> + + <!-- Example settings for Data & Sync --> + <string name="pref_header_data_sync">Data & sync</string> + <string name="pref_title_sync_frequency">Sync frequency</string> + + <string-array name="pref_sync_frequency_titles"> + <item>5 minutes</item> + <item>10 minutes</item> + <item>15 minutes</item> + <item>30 minutes</item> + <item>1 hour</item> + <item>3 hours</item> + <item>6 hours</item> + <item>Never</item> + </string-array> + <string-array name="pref_sync_frequency_values"> + <item>5</item> + <item>10</item> + <item>15</item> + <item>30</item> + <item>60</item> + <item>180</item> + <item>360</item> + <item>-1</item> + </string-array> + + <string name="pref_title_system_sync_settings">System sync settings</string> + + <!-- Example settings for Notifications --> + <string name="pref_header_notifications">Notifications</string> + <string name="pref_title_status_change_notifications">Status change notifications</string> + <string name="pref_title_ringtone">Ringtone</string> + <string name="pref_ringtone_silent">Silent</string> + <string name="pref_title_vibrate">Vibrate</string> + + <string name="pref_button_done">Done</string> + +</resources> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/values/styles.xml b/Android/Warpzone Status Widget/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a10ca492dd2610011d3979b4dc551f471fa27ab --- /dev/null +++ b/Android/Warpzone Status Widget/res/values/styles.xml @@ -0,0 +1,20 @@ +<resources> + + <!-- + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Light"> + <!-- + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + --> + </style> + + <!-- Application theme. --> + <style name="AppTheme" parent="AppBaseTheme"> + <!-- All customizations that are NOT specific to a particular API-level can go here. --> + </style> + +</resources> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/xml/pref_data_sync.xml b/Android/Warpzone Status Widget/res/xml/pref_data_sync.xml new file mode 100644 index 0000000000000000000000000000000000000000..b49a6cac3570fb97ba40969949b07a14f18a3ff0 --- /dev/null +++ b/Android/Warpzone Status Widget/res/xml/pref_data_sync.xml @@ -0,0 +1,25 @@ +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > + + <!-- + NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to + dismiss it. + --> + <!-- NOTE: ListPreference's summary should be set to its value by the activity code. --> + <ListPreference + android:defaultValue="15" + android:entries="@array/pref_sync_frequency_titles" + android:entryValues="@array/pref_sync_frequency_values" + android:key="sync_frequency" + android:negativeButtonText="@null" + android:positiveButtonText="@null" + android:title="@string/pref_title_sync_frequency" /> + + <!-- + This preference simply launches an intent when selected. Use this UI sparingly, per + design guidelines. + --> + <Preference android:title="@string/pref_title_system_sync_settings" > + <intent android:action="android.settings.SYNC_SETTINGS" /> + </Preference> + +</PreferenceScreen> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/xml/pref_headers.xml b/Android/Warpzone Status Widget/res/xml/pref_headers.xml new file mode 100644 index 0000000000000000000000000000000000000000..3dc449f1214510ad3f0ab270ff7e609a1cb45190 --- /dev/null +++ b/Android/Warpzone Status Widget/res/xml/pref_headers.xml @@ -0,0 +1,12 @@ +<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" > + + <!-- These settings headers are only used on tablets. --> + + <header + android:fragment="${packageName}.${activityClass}$DataSyncPreferenceFragment" + android:title="@string/pref_header_data_sync" /> + <header + android:fragment="${packageName}.${activityClass}$NotificationPreferenceFragment" + android:title="@string/pref_header_notifications" /> + +</preference-headers> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/xml/pref_notification.xml b/Android/Warpzone Status Widget/res/xml/pref_notification.xml new file mode 100644 index 0000000000000000000000000000000000000000..a535a7d585cc4bca1fce89fe58686b73ad5557f0 --- /dev/null +++ b/Android/Warpzone Status Widget/res/xml/pref_notification.xml @@ -0,0 +1,29 @@ +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > + + <!-- + A 'parent' preference, which enables/disables child preferences (below) + when checked/unchecked. + --> + <CheckBoxPreference + android:defaultValue="true" + android:key="notifications_status_change" + android:title="@string/pref_title_status_change_notifications" /> + + <!-- Allows the user to choose a ringtone in the 'notification' category. --> + <!-- NOTE: This preference will be enabled only when the checkbox above is checked. --> + <!-- NOTE: RingtonePreference's summary should be set to its value by the activity code. --> + <RingtonePreference + android:defaultValue="content://settings/system/notification_sound" + android:dependency="notifications_status_change" + android:key="notifications_status_change_ringtone" + android:ringtoneType="notification" + android:title="@string/pref_title_ringtone" /> + + <!-- NOTE: This preference will be enabled only when the checkbox above is checked. --> + <CheckBoxPreference + android:defaultValue="true" + android:dependency="notifications_status_change" + android:key="notifications_status_change_vibrate" + android:title="@string/pref_title_vibrate" /> + +</PreferenceScreen> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/res/xml/widget_provider.xml b/Android/Warpzone Status Widget/res/xml/widget_provider.xml new file mode 100644 index 0000000000000000000000000000000000000000..6861df846c9da96576bef352f60e69ce88b0cf05 --- /dev/null +++ b/Android/Warpzone Status Widget/res/xml/widget_provider.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" + android:minHeight="64dp" + android:minWidth="64dp" + android:configure="ms.warpzone.warpzonestatuswidget.SettingsActivity" + android:updatePeriodMillis="3600000"> +</appwidget-provider> \ No newline at end of file diff --git a/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/SettingsActivity.java b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/SettingsActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..ca940841ccbceeda7a9b8796d1d5ef59e9d7fffa --- /dev/null +++ b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/SettingsActivity.java @@ -0,0 +1,255 @@ +package ms.warpzone.warpzonestatuswidget; + +import android.annotation.TargetApi; +import android.appwidget.AppWidgetManager; +import android.content.ComponentName; +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.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; +import android.preference.RingtonePreference; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.ListView; + +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. + */ +public class SettingsActivity extends PreferenceActivity implements OnClickListener { + /** + * 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; + + private int widgetID; + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + setupSimplePreferencesScreen(); + + widgetID = AppWidgetManager.INVALID_APPWIDGET_ID; + Intent intent = getIntent(); + Bundle extras = intent.getExtras(); + if (extras != null) + widgetID = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + if (widgetID == AppWidgetManager.INVALID_APPWIDGET_ID) + finish(); + setResult(RESULT_CANCELED); + + ListView v = getListView(); + Button b = new Button(this); + b.setOnClickListener(this); + b.setText(R.string.pref_button_done); + v.addFooterView(b); + } + + public void onClick(View view) { + Log.d("Done", "First onUpdate broadcast sending..."); + final Context context = SettingsActivity.this; + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisAppWidget = new ComponentName(context.getPackageName(), SettingsActivity.class.getName()); + Intent firstUpdate = new Intent(context, WidgetProvider.class); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget); + firstUpdate.setAction("android.appwidget.action.APPWIDGET_UPDATE"); + firstUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); + context.sendBroadcast(firstUpdate); + Log.d("Done", "First onUpdate broadcast sent"); + Intent resultValue = new Intent(); + resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetID); + setResult(RESULT_OK, resultValue); + finish(); + } + + /** + * 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; + } + + // Add 'general' preferences. + addPreferencesFromResource(R.xml.pref_data_sync); + + // Add 'notifications' preferences, and a corresponding header. + PreferenceCategory fakeHeader = new PreferenceCategory(this); + fakeHeader.setTitle(R.string.pref_header_notifications); + getPreferenceScreen().addPreference(fakeHeader); + addPreferencesFromResource(R.xml.pref_notification); + + // Bind the summaries of EditText/List/Dialog/Ringtone preferences to + // their values. When their values change, their summaries are updated + // to reflect the new value, per the Android Design guidelines. + bindPreferenceSummaryToValue(findPreference("notifications_status_change_ringtone")); + bindPreferenceSummaryToValue(findPreference("sync_frequency")); + } + + /** {@inheritDoc} */ + @Override + public boolean onIsMultiPane() { + return isXLargeTablet(this) && !isSimplePreferences(this); + } + + /** + * 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. + */ + private static boolean isSimplePreferences(Context context) { + return ALWAYS_SIMPLE_PREFS + || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB + || !isXLargeTablet(context); + } + + /** {@inheritDoc} */ + @Override + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onBuildHeaders(List<Header> target) { + if (!isSimplePreferences(this)) { + loadHeadersFromResource(R.xml.pref_headers, target); + } + } + + /** + * A preference value change listener that updates the preference's summary + * to reflect its new value. + */ + private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + String stringValue = value.toString(); + + if (preference instanceof ListPreference) { + // 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] + : null); + + } 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 { + // For all other preferences, set the summary to the value's + // simple string representation. + preference.setSummary(stringValue); + } + return true; + } + }; + + /** + * 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 static 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. + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + PreferenceManager + .getDefaultSharedPreferences(preference.getContext()) + .getString(preference.getKey(), "")); + } + + /** + * 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 NotificationPreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_notification); + bindPreferenceSummaryToValue(findPreference("notifications_status_change_ringtone")); + } + } + + /** + * 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 DataSyncPreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_data_sync); + bindPreferenceSummaryToValue(findPreference("sync_frequency")); + } + } +} + diff --git a/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/StatusLoader.java b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/StatusLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..5fbac8284a3a13e6abd9a05b58c2e93d1b93915e --- /dev/null +++ b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/StatusLoader.java @@ -0,0 +1,91 @@ +package ms.warpzone.warpzonestatuswidget; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.annotation.TargetApi; +import android.os.Build; +import android.os.StrictMode; +import android.text.format.DateFormat; +import android.util.Log; + +public class StatusLoader { + + private static String loadJSONPage(String url) { + try { + URL uri = new URL(url); + HttpURLConnection connection = (HttpURLConnection) uri.openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + + String result = ""; + String line = reader.readLine(); + if(!line.contains("{")) + { + Log.d("loadJSONPage", "no JSON found on page."); + return null; + } + do { + result += line + "\n"; + } while ((line = reader.readLine()) != null); + + return result; + } catch (Exception e) { + if(e != null) + Log.d("loadJSONPage", e.getMessage()); + return null; + } + } + + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + private static void allowNetworkingInMainThread() { + //Allow Networking in this thread. + StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(policy); + } + + public static int getStatusImageID() { + + try { + allowNetworkingInMainThread(); + } + catch(Exception e) + { + Log.d("getStatusImageID", "allowNetworkingInMainThread not supported."); + } + + String content = loadJSONPage("http://warpzone.ms/api/status.php"); + if(content == null) { + Log.d("getStatusImageID", "Could not load status page."); + return R.drawable.warpzone_logo_small; + } + + JSONObject json; + try { + json = new JSONObject(content); + + long record_time = json.getLong("timestamp"); + long now = System.currentTimeMillis()/1000L; + + if((now - record_time) > 600) + { + Log.d("getStatusImageID", "Status record is too old."); + return R.drawable.warpzone_logo_orange_small; + } + + if(json.getInt("tuerOffen") != 0) + { + return R.drawable.warpzone_logo_green_small; + } + + return R.drawable.warpzone_logo_red_small; + } catch (JSONException e) { + Log.d("getStatusImageID", "Could not parse status JSON."); + return R.drawable.warpzone_logo_orange_small; + } + } +} \ No newline at end of file diff --git a/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/UpdateWidgetService.java b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/UpdateWidgetService.java new file mode 100644 index 0000000000000000000000000000000000000000..2bbca2668446cf0ea113be9459c3ba998fbad39f --- /dev/null +++ b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/UpdateWidgetService.java @@ -0,0 +1,53 @@ +package ms.warpzone.warpzonestatuswidget; + +import android.app.PendingIntent; +import android.app.Service; +import android.appwidget.AppWidgetManager; +import android.content.ComponentName; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; +import android.widget.RemoteViews; + +public class UpdateWidgetService extends Service { + + @Override + public void onStart(Intent intent, int startId) { + Log.d("onStart", "Called"); + // Create some random data + + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext()); + + int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + + ComponentName thisWidget = new ComponentName(getApplicationContext(), WidgetProvider.class); + int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget); + Log.d("onStart", "From Intent" + String.valueOf(allWidgetIds.length)); + Log.d("onStart", "Direct" + String.valueOf(allWidgetIds2.length)); + + for (int widgetId : allWidgetIds) { + RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout); + + // Set the text + remoteViews.setTextViewText(R.id.update, "Random: " + String.valueOf(number)); + + // Register an onClickListener + Intent clickIntent = new Intent(this.getApplicationContext(), WidgetProvider.class); + + clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds); + + PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent); + appWidgetManager.updateAppWidget(widgetId, remoteViews); + } + stopSelf(); + + super.onStart(intent, startId); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } +} \ No newline at end of file diff --git a/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/WidgetProvider.java b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/WidgetProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..389e8ee2877edb07dbae705a220f4adec0682202 --- /dev/null +++ b/Android/Warpzone Status Widget/src/ms/warpzone/warpzonestatuswidget/WidgetProvider.java @@ -0,0 +1,131 @@ +package ms.warpzone.warpzonestatuswidget; + +import java.util.Random; + +import android.annotation.TargetApi; +import android.app.AlarmManager; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Build; +import android.os.StrictMode; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.util.Log; +import android.widget.RemoteViews; + +public class WidgetProvider extends AppWidgetProvider { + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + Log.d("onUpdate", "called"); + + // get the widget views + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); + + // loading animation + remoteViews.setImageViewResource(R.id.imageView, android.R.drawable.stat_notify_sync);//ic_popup_sync); + for (int widgetId : appWidgetIds) + sendUpdate(context, appWidgetManager, widgetId, remoteViews); + + // load the settings + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + + // keep the refresh timer running + updateAlarm(context, settings, appWidgetIds); + + // load status and send notification, if appropriate + int status = StatusLoader.getStatusImageID(); + if(statusChanged(context, settings, status) && settings.getBoolean("notifications_status_change", false)) + sendNotification(context, settings); + + // set new status image + remoteViews.setImageViewResource(R.id.imageView, status); + for (int widgetId : appWidgetIds) + sendUpdate(context, appWidgetManager, widgetId, remoteViews); + } + + private void updateAlarm(Context context, SharedPreferences settings, int[] appWidgetIds) { + Intent intent = get_ACTION_APPWIDGET_UPDATE_Intent(context); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetIds[0], intent, PendingIntent.FLAG_UPDATE_CURRENT); + + AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + alarm.cancel(pendingIntent); + int minutes = Integer.parseInt(settings.getString("sync_frequency", "15")); + if(minutes > 0) + { + long interval = 1000*60*minutes; + alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + interval, interval, pendingIntent); + } + } + + private void sendNotification(Context context, SharedPreferences settings) { + + int icon = settings.getInt("status", -1); + Uri sound = Uri.parse(settings.getString("notifications_status_change_ringtone", "content://settings/system/notification_sound")); + boolean vibrate = settings.getBoolean("notifications_status_change_vibrate", false); + + String title = "Warpzone Status"; + String message = "Der Warpzone-Status hat sich geändert!"; + + Intent notificationIntent = new Intent(context, WidgetProvider.class); + PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); + + Notification notification = new Notification(icon, message, System.currentTimeMillis()); + notification.sound = sound; + notification.flags = Notification.FLAG_AUTO_CANCEL; + if(vibrate) + notification.defaults = Notification.DEFAULT_VIBRATE; + notification.setLatestEventInfo(context, title, message, contentIntent); + + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + nm.notify(new Random().nextInt(), notification); + } + + private boolean statusChanged(Context context, SharedPreferences settings, int status_new) + { + if(status_new != R.drawable.warpzone_logo_small && settings.getInt("status", -1) != status_new) + { + SharedPreferences.Editor editor = settings.edit(); + editor.putInt("status", status_new); + editor.commit(); + return true; + } + return false; + } + + private void sendUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId, RemoteViews remoteViews) + { + //When user click on the label, update ALL the instances of the widget. + Intent labelIntent = get_ACTION_APPWIDGET_UPDATE_Intent(context); + PendingIntent labelPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, labelIntent, PendingIntent.FLAG_UPDATE_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.imageView, labelPendingIntent); + Log.d("updateAppWidget", "Updated ID: " + appWidgetId); + //Call the Manager to ensure the changes take effect. + appWidgetManager.updateAppWidget(appWidgetId, remoteViews); + } + + /** + * Utility method to ensure that when we want an Intent that fire ACTION_APPWIDGET_UPDATE, the extras are correct.<br> + * The default implementation of onReceive() will discard it if we don't add the ids of all the instances. + * @param context + * @return + */ + protected Intent get_ACTION_APPWIDGET_UPDATE_Intent(Context context) { + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisAppWidget = new ComponentName(context.getPackageName(), WidgetProvider.class.getName()); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget); + Intent intent = new Intent(context, WidgetProvider.class); + intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); + return intent; + } +}