diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2014-11-30 23:55:54 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2014-12-01 00:17:04 +0100 |
commit | 7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d (patch) | |
tree | 35d8a59e3d5ae1e0b600d91b2ac4283380bdc896 | |
download | fiken-display-android-7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d.tar.gz fiken-display-android-7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d.tar.bz2 fiken-display-android-7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d.tar.xz fiken-display-android-7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d.zip |
o Initial import of Fiken Status Display app.
54 files changed, 2148 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afbdab3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..7d5a8b0 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Display
\ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000..29ab470 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectCodeStyleSettingsManager"> + <option name="PER_PROJECT_SETTINGS"> + <value> + <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" /> + <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" /> + <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND"> + <value /> + </option> + <option name="IMPORT_LAYOUT_TABLE"> + <value> + <package name="android" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="com" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="junit" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="net" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="org" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="java" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="javax" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="" withSubpackages="true" static="true" /> + <emptyLine /> + </value> + </option> + <option name="RIGHT_MARGIN" value="100" /> + <AndroidXmlCodeStyleSettings> + <option name="USE_CUSTOM_SETTINGS" value="true" /> + </AndroidXmlCodeStyleSettings> + <XML> + <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" /> + </XML> + <codeStyleSettings language="XML"> + <option name="FORCE_REARRANGE_MODE" value="1" /> + <indentOptions> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> + </indentOptions> + <arrangement> + <rules> + <rule> + <match> + <AND> + <NAME>xmlns:android</NAME> + <XML_NAMESPACE>Namespace:</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>xmlns:.*</NAME> + <XML_NAMESPACE>Namespace:</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*:id</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>.*:name</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>name</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>style</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*:layout_width</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>.*:layout_height</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + <rule> + <match> + <AND> + <NAME>.*:layout_.*</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*:width</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*:height</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>.*</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </rules> + </arrangement> + </codeStyleSettings> + </value> + </option> + <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" /> + </component> +</project> + diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..217af47 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CompilerConfiguration"> + <option name="DEFAULT_COMPILER" value="Javac" /> + <resourceExtensions /> + <wildcardResourcePatterns> + <entry name="!?*.java" /> + <entry name="!?*.form" /> + <entry name="!?*.class" /> + <entry name="!?*.groovy" /> + <entry name="!?*.scala" /> + <entry name="!?*.flex" /> + <entry name="!?*.kt" /> + <entry name="!?*.clj" /> + </wildcardResourcePatterns> + <annotationProcessing> + <profile default="true" name="Default" enabled="false"> + <processorPath useClasspath="true" /> + </profile> + </annotationProcessing> + </component> +</project> + diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ +<component name="CopyrightManager"> + <settings default="" /> +</component>
\ No newline at end of file diff --git a/.idea/dictionaries/trygvis.xml b/.idea/dictionaries/trygvis.xml new file mode 100644 index 0000000..9afac00 --- /dev/null +++ b/.idea/dictionaries/trygvis.xml @@ -0,0 +1,10 @@ +<component name="ProjectDictionaryState"> + <dictionary name="trygvis"> + <words> + <w>fiken</w> + <w>rssi</w> + <w>trygvis</w> + <w>xxxx</w> + </words> + </dictionary> +</component>
\ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> +</project> + diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..736c7b5 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="GradleSettings"> + <option name="linkedExternalProjectsSettings"> + <GradleProjectSettings> + <option name="distributionType" value="DEFAULT_WRAPPED" /> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="modules"> + <set> + <option value="$PROJECT_DIR$" /> + <option value="$PROJECT_DIR$/app" /> + </set> + </option> + </GradleProjectSettings> + </option> + </component> +</project> + diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..2497215 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="EntryPointsManager"> + <entry_points version="2.0" /> + </component> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/build/classes" /> + </component> +</project> + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..342f96e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> + <module fileurl="file://$PROJECT_DIR$/fiken-display-android.iml" filepath="$PROJECT_DIR$/fiken-display-android.iml" /> + </modules> + </component> +</project> + diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ +<component name="DependencyValidationManager"> + <state> + <option name="SKIP_IMPORT_STATEMENTS" value="false" /> + </state> +</component>
\ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..275077f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..6a4dade --- /dev/null +++ b/app/app.iml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="fiken-display-android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="android-gradle" name="Android-Gradle"> + <configuration> + <option name="GRADLE_PROJECT_PATH" value=":app" /> + </configuration> + </facet> + <facet type="android" name="Android"> + <configuration> + <option name="SELECTED_BUILD_VARIANT" value="debug" /> + <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> + <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" /> + <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" /> + <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" /> + <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" /> + <option name="ALLOW_USER_CONFIGURATION" value="false" /> + <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> + <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> + <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" /> + <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" /> + <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> + <excludeFolder url="file://$MODULE_DIR$/build/outputs" /> + <excludeFolder url="file://$MODULE_DIR$/build/tmp" /> + </content> + <orderEntry type="jdk" jdkName="Android API 18 Platform" jdkType="Android SDK" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> + diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4073375 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 18 + buildToolsVersion "19.1.0" + + defaultConfig { + applicationId "no.topi.fiken.display" + minSdkVersion 18 + targetSdkVersion 18 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + runProguard false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..875c86a --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/trygvis/opt/android-sdk-linux/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/app/src/androidTest/java/no/topi/fiken/display/ApplicationTest.java b/app/src/androidTest/java/no/topi/fiken/display/ApplicationTest.java new file mode 100644 index 0000000..c306301 --- /dev/null +++ b/app/src/androidTest/java/no/topi/fiken/display/ApplicationTest.java @@ -0,0 +1,13 @@ +package no.topi.fiken.display; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> + */ +public class ApplicationTest extends ApplicationTestCase<Application> { + public ApplicationTest() { + super(Application.class); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..35956d8 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="no.topi.fiken.display" > + + <!-- + Declare this required feature if you want to make the app available to BLE-capable + devices only. If you want to make your app available to devices that don't support BLE, + you should omit this in the manifest. Instead, determine BLE capability by using + PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) + --> + <uses-feature + android:name="android.hardware.bluetooth_le" + android:required="true" /> + + <uses-permission android:name="android.permission.BLUETOOTH" /> + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> + + <!-- + <application android:label="@string/app_name" + android:icon="@drawable/ic_launcher" + android:theme="@android:style/Theme.Holo.Light"> + <activity android:name=".DeviceScanActivity" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <activity android:name=".DeviceControlActivity"/> + <service android:name=".BluetoothLeService" android:enabled="true"/> + </application> + --> + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name="no.topi.fiken.display.MainActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity + android:name="no.topi.fiken.display.DisplayControlActivity" + android:label="@string/title_activity_display_control" /> + + <service + android:name=".DefaultDisplayService" + android:enabled="true" /> + </application> + +</manifest> diff --git a/app/src/main/java/no/topi/fiken/display/Constants.java b/app/src/main/java/no/topi/fiken/display/Constants.java new file mode 100644 index 0000000..f568e1c --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/Constants.java @@ -0,0 +1,10 @@ +package no.topi.fiken.display; + +import java.util.UUID; + +public interface Constants { + String TRYGVIS_IO_BASE_UUID = "32D0xxxx-035D-59C5-70D3-BC8E4A1FD83F"; + UUID TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID = UUID.fromString(TRYGVIS_IO_BASE_UUID.replace("xxxx", "0001")); + UUID TRYGVIS_IO_GAUGE_UUID = UUID.fromString(TRYGVIS_IO_BASE_UUID.replace("xxxx", "0002")); + UUID TRYGVIS_IO_LED_UUID = UUID.fromString(TRYGVIS_IO_BASE_UUID.replace("xxxx", "0003")); +} diff --git a/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java b/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java new file mode 100644 index 0000000..b1aa2e7 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java @@ -0,0 +1,255 @@ +package no.topi.fiken.display; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothManager; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +public class DefaultDisplayService extends Service implements DisplayService { + private final Context context = DefaultDisplayService.this; + private final static String TAG = DefaultDisplayService.class.getSimpleName(); + + private final IBinder binder = new LocalBinder(this); + + private BluetoothManager mBluetoothManager; + private BluetoothAdapter mBluetoothAdapter; + private BluetoothGattService displayService; + private BluetoothGatt gatt; + + private Handler handler; + private int UPDATE_RSSI_DELAY = 1000; + + private Runnable updateRssi = new Runnable() { + @Override + public void run() { + if(gatt != null) { + gatt.readRemoteRssi(); + } + + handler.postDelayed(this, UPDATE_RSSI_DELAY); + } + }; + + public static enum ServiceState { + BROKEN, + IDLE, + SCANNING, + CONNECTED, + } + + private ServiceState serviceState = ServiceState.BROKEN; + + @Override + public IBinder onBind(Intent intent) { + return binder; + } + + @Override + public void onCreate() { + handler = new Handler(); + + handler.postDelayed(updateRssi, UPDATE_RSSI_DELAY); + } + + public boolean initialize() { + // For API level 18 and above, get a reference to BluetoothAdapter through + // BluetoothManager. + if (mBluetoothManager == null) { + mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetoothManager == null) { + Log.e(TAG, "Unable to initialize BluetoothManager."); + return false; + } + } + + mBluetoothAdapter = mBluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + Log.e(TAG, "Unable to obtain a BluetoothAdapter."); + return false; + } + + Log.e(TAG, "Bluetooth initialized"); + + serviceState = ServiceState.IDLE; + + return true; + } + + @Override + public boolean connect(final String address) { + if (serviceState != ServiceState.IDLE) { + if (!(serviceState == ServiceState.CONNECTED && gatt.getDevice().getAddress().equals(address))) { + Log.e(TAG, "connect(): Not idle: " + serviceState); + return false; + } + + Log.i(TAG, "connect(): already connected: " + serviceState); + return true; + } + + BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); + + gatt = device.connectGatt(this, false, new BluetoothGattCallback() { + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { +// Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show(); + if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { + boolean ok = gatt.discoverServices(); + + if (!ok) { + disconnect(); + } else { + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); + intent.putExtra(IntentExtra.CONNECTED.name(), true); + sendBroadcast(intent); + } + } else { + Log.w(TAG, "Could not connect to device"); +// Toast.makeText(context, "Could not connect to device", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + Log.i(TAG, "onServicesDiscovered"); + + Log.i(TAG, "Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID = " + Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID); + + for (BluetoothGattService bluetoothGattService : gatt.getServices()) { + Log.i(TAG, "bluetoothGattService.getUuid() = " + bluetoothGattService.getUuid()); + } + + displayService = gatt.getService(Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID); + + Log.i(TAG, "service=" + displayService); + + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); + intent.putExtra(IntentExtra.DEVICE_IS_DISPLAY.name(), displayService != null); + sendBroadcast(intent); + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + Log.i(TAG, "onCharacteristicRead"); + } + + @Override + public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + Log.i(TAG, "onCharacteristicWrite"); + } + + @Override + public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + Log.i(TAG, "onCharacteristicChanged"); + } + + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + Log.i(TAG, "onDescriptorRead"); + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + Log.i(TAG, "onDescriptorWrite"); + } + + @Override + public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { + Log.i(TAG, "onReliableWriteCompleted"); + } + + @Override + public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { + Log.i(TAG, "onReadRemoteRssi, status=" + status + ", rssi=" + rssi); + if (status == BluetoothGatt.GATT_SUCCESS) { + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), gatt.getDevice().getAddress()); + intent.putExtra(IntentExtra.RSSI.name(), rssi); + sendBroadcast(intent); + } + } + }); + + if (gatt != null) { + serviceState = ServiceState.CONNECTED; + return true; + } else { + return false; + } + } + + @Override + public void disconnect() { + if (serviceState != ServiceState.CONNECTED) { + Log.d(TAG, "disconnect(): Not connected: " + serviceState); + return; + } + + serviceState = ServiceState.IDLE; + + if (gatt != null) { + try { + gatt.disconnect(); + } catch (Exception e) { + Log.w(TAG, "gatt.disconnect()", e); + } + try { + gatt.close(); + } catch (Exception e) { + Log.w(TAG, "gatt.close()", e); + } + gatt = null; + } + + displayService = null; + } + + @Override + public void startScan() { + if (serviceState != ServiceState.IDLE) { + Toast.makeText(context, "startScan(): Not idle", Toast.LENGTH_SHORT).show(); + return; + } + + serviceState = ServiceState.SCANNING; + + mBluetoothAdapter.startLeScan(leScanCallback); + } + + @Override + public void stopScan() { + Log.d(TAG, "stopScan(): stopping scanning"); + + if (serviceState != ServiceState.SCANNING) { + Log.d(TAG, "stopScan(): not scanning"); + return; + } + mBluetoothAdapter.stopLeScan(leScanCallback); + serviceState = ServiceState.IDLE; + } + + private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { + @Override + public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { + Log.i(TAG, "onLeScan()"); + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), device.getAddress()); + intent.putExtra(IntentExtra.DEVICE_NAME.name(), device.getName()); + intent.putExtra(IntentExtra.RSSI.name(), rssi); + sendBroadcast(intent); + } + }; +} diff --git a/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java b/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java new file mode 100644 index 0000000..1147c0c --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java @@ -0,0 +1,141 @@ +package no.topi.fiken.display; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.Menu; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import static java.lang.String.valueOf; +import static no.topi.fiken.display.DisplayService.DeviceInfo; +import static no.topi.fiken.display.DisplayService.IntentAction; +import static no.topi.fiken.display.DisplayService.IntentExtra; +import static no.topi.fiken.display.DisplayService.LocalBinder; + +public class DisplayControlActivity extends Activity { + private final static String TAG = DisplayControlActivity.class.getSimpleName(); + + private DisplayService displayService; + private DeviceInfo deviceInfo; + + private TextView deviceNameView; + private TextView deviceRssiView; + private LinearLayout gaugesLayout; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_display_control); + + final Intent intent = getIntent(); + String deviceAddress = intent.getStringExtra(IntentExtra.DEVICE_ADDRESS.name()); + deviceInfo = new DeviceInfo(deviceAddress, 0); + deviceInfo.name = intent.getStringExtra(IntentExtra.DEVICE_NAME.name()); + + Intent displayServiceIntent = new Intent(this, DefaultDisplayService.class); + bindService(displayServiceIntent, serviceConnection, BIND_AUTO_CREATE); + + deviceNameView = (TextView) findViewById(R.id.device_name); + deviceRssiView = (TextView) findViewById(R.id.device_rssi); + gaugesLayout = (LinearLayout) findViewById(R.id.gauges); + + Button disconnectButton = (Button) findViewById(R.id.button_disconnect); + disconnectButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + disconnect(); + } + }); + + updateValues(); + } + + private void updateValues() { + deviceNameView.setText(deviceInfo.name != null ? deviceInfo.name : getText(R.string.name_unknown)); + deviceRssiView.setText(getText(R.string.rssi) + ": " + (deviceInfo.rssi != 0 ? valueOf(deviceInfo.rssi) : "")); + } + + @Override + protected void onResume() { + super.onResume(); + registerReceiver(displayServiceBroadcastReceiver, IntentAction.ALL_FILTER); + } + + @Override + protected void onPause() { + super.onPause(); + unregisterReceiver(displayServiceBroadcastReceiver); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + displayService.disconnect(); + unbindService(serviceConnection); + displayService = null; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_display_control, menu); + return true; + } + + public void disconnect() { + if (displayService != null) { + displayService.disconnect(); + } + + finish(); + } + + private final ServiceConnection serviceConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + displayService = ((LocalBinder) service).getService(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + displayService = null; + } + }; + + private final BroadcastReceiver displayServiceBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + + IntentAction action = IntentAction.valueOf(intent); + + String deviceAddress = intent.getStringExtra(IntentExtra.DEVICE_ADDRESS.name()); + + if (action == IntentAction.DEVICE_UPDATE && deviceInfo.address.equals(deviceAddress)) { + runOnUiThread(new Runnable() { + @Override + public void run() { + deviceInfo.update(intent); + + if (intent.hasExtra(IntentExtra.CONNECTED.name())) { + boolean connected = intent.getBooleanExtra(IntentExtra.CONNECTED.name(), false); + + if (!connected) { + finish(); + } + } + updateValues(); + } + }); + } + } + }; +} diff --git a/app/src/main/java/no/topi/fiken/display/DisplayService.java b/app/src/main/java/no/topi/fiken/display/DisplayService.java new file mode 100644 index 0000000..c907138 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/DisplayService.java @@ -0,0 +1,102 @@ +package no.topi.fiken.display; + +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; + +public interface DisplayService { + + enum IntentExtra { + DEVICE_NAME, + DEVICE_ADDRESS, + DEVICE_IS_DISPLAY, + RSSI, + SCANNING, + CONNECTED, + } + + public static enum IntentAction { + DEVICE_UPDATE; + + private final String key = getClass().getName() + "." + name(); + + public Intent intent() { + return new Intent(key); + } + + public static final IntentFilter ALL_FILTER = new IntentFilter() {{ + for (DefaultDisplayService.IntentAction intentAction : DefaultDisplayService.IntentAction.values()) { + addAction(intentAction.key); + } + }}; + + public static IntentAction valueOf(Intent intent) { + try { + return valueOf(intent.getAction().replaceAll(".*\\.", "")); + } catch (IllegalArgumentException e) { + return null; + } + } + } + + public class LocalBinder extends Binder { + private final DisplayService service; + + public LocalBinder(DisplayService service) { + this.service = service; + } + + DisplayService getService() { + return service; + } + } + + boolean initialize(); + + void startScan(); + + void stopScan(); + + boolean connect(String address); + + public void disconnect(); + + class DeviceInfo { + final String address; + int rssi = 0; + Boolean isDisplay = null; + String name; + + DeviceInfo(String address, int rssi) { + this.address = address; + this.rssi = rssi; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DeviceInfo that = (DeviceInfo) o; + + return address.equals(that.address); + } + + @Override + public int hashCode() { + return address.hashCode(); + } + + public void update(Intent intent) { + if (intent.hasExtra(IntentExtra.DEVICE_IS_DISPLAY.name())) { + isDisplay = intent.getBooleanExtra(IntentExtra.DEVICE_IS_DISPLAY.name(), false); + } + if (intent.hasExtra(IntentExtra.RSSI.name())) { + rssi = intent.getIntExtra(IntentExtra.RSSI.name(), 0); + } + if (intent.hasExtra(IntentExtra.DEVICE_NAME.name())) { + name = intent.getStringExtra(IntentExtra.DEVICE_NAME.name()); + } + } + } +} diff --git a/app/src/main/java/no/topi/fiken/display/ExceptionHandler.java b/app/src/main/java/no/topi/fiken/display/ExceptionHandler.java new file mode 100644 index 0000000..3d4560b --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/ExceptionHandler.java @@ -0,0 +1,22 @@ +package no.topi.fiken.display; + +import android.util.Log; + +public class ExceptionHandler implements Thread.UncaughtExceptionHandler { + private final static String TAG = DefaultDisplayService.class.getSimpleName(); + + public static final ExceptionHandler EXCEPTION_HANDLER = new ExceptionHandler(); + + @Override + public void uncaughtException(Thread thread, Throwable ex) { + Log.e(TAG, "Uncaught", ex); + + if (ex instanceof RuntimeException) { + throw (RuntimeException) ex; + } + if (ex instanceof Error) { + throw (Error) ex; + } + throw new RuntimeException(ex); + } +} diff --git a/app/src/main/java/no/topi/fiken/display/MainActivity.java b/app/src/main/java/no/topi/fiken/display/MainActivity.java new file mode 100644 index 0000000..d9dc073 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/MainActivity.java @@ -0,0 +1,335 @@ +package no.topi.fiken.display; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.ListActivity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; + +import static java.lang.String.valueOf; +import static no.topi.fiken.display.DisplayService.IntentAction; +import static no.topi.fiken.display.DisplayService.IntentExtra; +import static no.topi.fiken.display.ExceptionHandler.EXCEPTION_HANDLER; + +public class MainActivity extends ListActivity { + private final static String TAG = MainActivity.class.getSimpleName(); + + // Stops scanning after 10 seconds. + private static final long SCAN_PERIOD = 3 * 1000; + + private static final int REQUEST_ENABLE_BT = 1; + + private DisplayListAdapter displayList; + private Handler handler; + private BluetoothAdapter mBluetoothAdapter; + private boolean mScanning; + private DisplayService displayService; + private String deviceToShow; + + @Override + protected void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + Thread.setDefaultUncaughtExceptionHandler(EXCEPTION_HANDLER); + super.onCreate(savedInstanceState); + + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setTitle(R.string.title_devices); + } + handler = new Handler(); + + // Use this check to determine whether BLE is supported on the device. Then you can + // selectively disable BLE-related features. + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + } + + // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to + // BluetoothAdapter through BluetoothManager. + final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothAdapter = bluetoothManager.getAdapter(); + + // Checks if Bluetooth is supported on the device. + if (mBluetoothAdapter == null) { + Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + } + + ServiceConnection serviceConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + displayService = ((DisplayService.LocalBinder) service).getService(); + if (!displayService.initialize()) { + finish(); + } + + startScan(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + stopScan(); + displayService = null; + } + }; + + Intent displayServiceIntent = new Intent(this, DefaultDisplayService.class); + bindService(displayServiceIntent, serviceConnection, BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + Log.i(TAG, "onResume"); + + super.onResume(); + + // Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled, + // fire an intent to display a dialog asking the user to grant permission to enable it. + if (!mBluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } + + registerReceiver(displayServiceBroadcastReceiver, IntentAction.ALL_FILTER); + } + + @Override + protected void onPause() { + Log.i(TAG, "onPause"); + + super.onPause(); + stopScan(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.i(TAG, "onActivityResult"); + + // User chose not to enable Bluetooth. + if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) { + finish(); + return; + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + Log.i(TAG, "onCreateOptionsMenu"); + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + + if (!mScanning) { + menu.findItem(R.id.menu_stop).setVisible(false); + menu.findItem(R.id.menu_scan).setVisible(true); + menu.findItem(R.id.menu_refresh).setActionView(null); + } else { + menu.findItem(R.id.menu_stop).setVisible(true); + menu.findItem(R.id.menu_scan).setVisible(false); + menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_indeterminate_progress); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + Log.i(TAG, "onOptionsItemSelected"); + + switch (item.getItemId()) { + case R.id.menu_scan: + startScan(); + break; + case R.id.menu_stop: + stopScan(); + break; + } + return super.onOptionsItemSelected(item); + } + + private void startScan() { + displayList = new DisplayListAdapter(); + setListAdapter(displayList); + + displayService.startScan(); + + // Stops scanning after a pre-defined scan period. + handler.postDelayed(new Runnable() { + @Override + public void run() { + displayService.stopScan(); + invalidateOptionsMenu(); + } + }, SCAN_PERIOD); + } + + private void stopScan() { + if (displayService != null) { + displayService.stopScan(); + } + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + stopScan(); + + DisplayService.DeviceInfo state = displayList.getDevice(position); + + if (!displayService.connect(state.address)) { + Toast.makeText(this, "Could not connect to " + state.address, Toast.LENGTH_SHORT).show(); + } else { + deviceToShow = state.address; + } + } + + private final BroadcastReceiver displayServiceBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + runOnUiThread(new Runnable() { + @Override + public void run() { + IntentAction action = IntentAction.valueOf(intent); + + String deviceAddress = intent.getStringExtra(IntentExtra.DEVICE_ADDRESS.name()); + + if (action == IntentAction.DEVICE_UPDATE && deviceAddress != null) { + DisplayService.DeviceInfo device = displayList.getDevice(deviceAddress, true); + + device.update(intent); + + if (intent.hasExtra(IntentExtra.CONNECTED.name())) { + boolean connected = intent.getBooleanExtra(IntentExtra.CONNECTED.name(), false); + + if (connected) { + if (deviceToShow != null && deviceToShow.equals(device.address)) { + Log.i(TAG, "connected to " + deviceToShow); + final Intent intent = new Intent(context, DisplayControlActivity.class); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), device.address); + intent.putExtra(IntentExtra.DEVICE_NAME.name(), device.name); + startActivity(intent); + } + } + } + displayList.notifyDataSetChanged(); + } + + if (intent.hasExtra(IntentExtra.SCANNING.name())) { + mScanning = intent.getBooleanExtra(IntentExtra.SCANNING.name(), false); + invalidateOptionsMenu(); + } + } + }); + } + }; + + static class ViewHolder { + final TextView deviceName; + final TextView deviceAddress; + final TextView rssi; + final TextView isDisplay; + + ViewHolder(TextView deviceName, TextView deviceAddress, TextView rssi, TextView isDisplay) { + this.deviceName = deviceName; + this.deviceAddress = deviceAddress; + this.rssi = rssi; + this.isDisplay = isDisplay; + } + } + + private class DisplayListAdapter extends BaseAdapter { + private List<DisplayService.DeviceInfo> devices = new ArrayList<DisplayService.DeviceInfo>(); + private LayoutInflater inflater = MainActivity.this.getLayoutInflater(); + + public DisplayService.DeviceInfo getDevice(int position) { + return devices.get(position); + } + + public DisplayService.DeviceInfo getDevice(String address, boolean create) { + for (DisplayService.DeviceInfo device : devices) { + if (device.address.equals(address)) { + return device; + } + } + + DisplayService.DeviceInfo deviceInfo = null; + if (create) { + deviceInfo = new DisplayService.DeviceInfo(address, 0); + devices.add(deviceInfo); + } + return deviceInfo; + } + + @Override + public int getCount() { + return devices.size(); + } + + @Override + public Object getItem(int i) { + return devices.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + ViewHolder viewHolder; + + if (view == null) { + view = inflater.inflate(R.layout.listitem_device, null); + viewHolder = new ViewHolder( + (TextView) view.findViewById(R.id.device_name), + (TextView) view.findViewById(R.id.device_address), + (TextView) view.findViewById(R.id.device_rssi), + (TextView) view.findViewById(R.id.device_isDisplay)); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + DisplayService.DeviceInfo state = devices.get(i); + if (state.name != null && state.name.length() > 0) { + viewHolder.deviceName.setText(state.name); + } else { + viewHolder.deviceName.setText(R.string.unknown_device); + } + viewHolder.deviceAddress.setText(state.address); + + viewHolder.rssi.setText(getText(R.string.rssi) + ": " + + (state.rssi != 0 ? valueOf(state.rssi) : getText(R.string.rssi_unknown))); + + viewHolder.isDisplay.setText("Is display: " + + (state.isDisplay != null ? state.isDisplay : "unknown")); + view.setClickable(state.isDisplay != null && state.isDisplay); + + return view; + } + } +} diff --git a/app/src/main/res/demo/demo/activity_main2.xml b/app/src/main/res/demo/demo/activity_main2.xml new file mode 100644 index 0000000..b48f349 --- /dev/null +++ b/app/src/main/res/demo/demo/activity_main2.xml @@ -0,0 +1,36 @@ +<!-- + Copyright 2013 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. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout style="@style/Widget.SampleMessageTile" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView style="@style/Widget.SampleMessage" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/horizontal_page_margin" + android:layout_marginRight="@dimen/horizontal_page_margin" + android:layout_marginTop="@dimen/vertical_page_margin" + android:layout_marginBottom="@dimen/vertical_page_margin" + android:text="@string/intro_message" /> + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/demo/values/base-strings.xml b/app/src/main/res/demo/values/base-strings.xml new file mode 100644 index 0000000..6071269 --- /dev/null +++ b/app/src/main/res/demo/values/base-strings.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2013 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. +--> +<resources> +<!-- + <string name="app_name">BluetoothLeGatt</string> +--> + <string name="intro_message"> + <![CDATA[ + + + This sample demonstrates how to use the Bluetooth LE Generic Attribute Profile (GATT) + to transmit arbitrary data between devices. + + + ]]> + </string> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/demo/values/template-dimens.xml b/app/src/main/res/demo/values/template-dimens.xml new file mode 100644 index 0000000..afacaf5 --- /dev/null +++ b/app/src/main/res/demo/values/template-dimens.xml @@ -0,0 +1,32 @@ +<!-- + Copyright 2013 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. + --> + +<resources> + + <!-- Define standard dimensions to comply with Holo-style grids and rhythm. --> + + <dimen name="margin_tiny">4dp</dimen> + <dimen name="margin_small">8dp</dimen> + <dimen name="margin_medium">16dp</dimen> + <dimen name="margin_large">32dp</dimen> + <dimen name="margin_huge">64dp</dimen> + + <!-- Semantic definitions --> + + <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen> + <dimen name="vertical_page_margin">@dimen/margin_medium</dimen> + +</resources>
\ No newline at end of file diff --git a/app/src/main/res/demo/values/template-styles.xml b/app/src/main/res/demo/values/template-styles.xml new file mode 100644 index 0000000..f23e542 --- /dev/null +++ b/app/src/main/res/demo/values/template-styles.xml @@ -0,0 +1,44 @@ +<!-- + Copyright 2013 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. + --> + +<resources> + + <!-- Activity themes --> + + <style name="Theme.Base" parent="android:Theme.Light"/> + + <style name="Theme.Sample" parent="Theme.Base"/> + + <!-- + <style name="AppTheme" parent="Theme.Sample" /> + --> + <!-- Widget styling --> + + <style name="Widget"/> + + <style name="Widget.SampleMessage"> + <item name="android:textAppearance">?android:textAppearanceMedium</item> + <item name="android:lineSpacingMultiplier">1.1</item> + </style> + + <style name="Widget.SampleMessageTile"> + <item name="android:background">@drawable/tile</item> + <item name="android:shadowColor">#7F000000</item> + <item name="android:shadowDy">-3.5</item> + <item name="android:shadowRadius">2</item> + </style> + +</resources> diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96a442e --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..359047d --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..71c6d76 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..4df1894 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/layout/actionbar_indeterminate_progress.xml b/app/src/main/res/layout/actionbar_indeterminate_progress.xml new file mode 100644 index 0000000..c68bc3c --- /dev/null +++ b/app/src/main/res/layout/actionbar_indeterminate_progress.xml @@ -0,0 +1,23 @@ +<!-- + Copyright 2013 Google Inc. + + 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. + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="wrap_content" + android:layout_width="56dp" + android:minWidth="56dp"> + <ProgressBar android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center"/> +</FrameLayout> diff --git a/app/src/main/res/layout/activity_display_control.xml b/app/src/main/res/layout/activity_display_control.xml new file mode 100644 index 0000000..4151184 --- /dev/null +++ b/app/src/main/res/layout/activity_display_control.xml @@ -0,0 +1,42 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context="no.topi.fiken.display.DisplayControlActivity"> + + <TextView + android:id="@+id/device_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="24sp" + android:layout_alignParentEnd="true"/> + + <TextView + android:id="@+id/device_rssi" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="12sp" + android:layout_below="@+id/device_name"/> + + <Button + android:id="@+id/button_disconnect" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/disconnect" + android:layout_below="@+id/device_rssi" + /> + + <LinearLayout + android:id="@+id/gauges" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_below="@+id/button_disconnect" + android:layout_alignParentStart="true"> + </LinearLayout> + +</RelativeLayout> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..ead92a8 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,7 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" + tools:ignore="MergeRootFrame"/> diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml new file mode 100644 index 0000000..8958013 --- /dev/null +++ b/app/src/main/res/layout/fragment_main.xml @@ -0,0 +1,36 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" + android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context=".MainActivity$PlaceholderFragment"> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="New Button" + android:id="@+id/button" + android:layout_alignParentBottom="true" + android:layout_alignParentEnd="true" + android:layout_alignParentStart="true" /> + + <ProgressBar + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/progressBar" + android:layout_centerVertical="true" + android:layout_centerHorizontal="true" + android:visibility="gone" /> + + <ListView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/listView" + android:layout_toStartOf="@+id/progressBar" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_above="@+id/button" + android:layout_alignParentEnd="true" /> + +</RelativeLayout> diff --git a/app/src/main/res/layout/gatt_services_characteristics.xml b/app/src/main/res/layout/gatt_services_characteristics.xml new file mode 100644 index 0000000..0156afd --- /dev/null +++ b/app/src/main/res/layout/gatt_services_characteristics.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp"> + <LinearLayout android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp"> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_device_address" + android:textSize="18sp"/> + <Space android:layout_width="5dp" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/device_address" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="18sp"/> + </LinearLayout> + <LinearLayout android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp"> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_state" + android:textSize="18sp"/> + <Space android:layout_width="5dp" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/connection_state" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/disconnected" + android:textSize="18sp"/> + </LinearLayout> + <LinearLayout android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp"> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_data" + android:textSize="18sp"/> + <Space android:layout_width="5dp" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/data_value" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/no_data" + android:textSize="18sp"/> + </LinearLayout> + <ExpandableListView android:id="@+id/gatt_services_list" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> +</LinearLayout> diff --git a/app/src/main/res/layout/listitem_device.xml b/app/src/main/res/layout/listitem_device.xml new file mode 100644 index 0000000..54f529e --- /dev/null +++ b/app/src/main/res/layout/listitem_device.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/device_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="24sp"/> + + <TextView + android:id="@+id/device_address" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="12sp"/> + + <TextView + android:id="@+id/device_rssi" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="12sp"/> + + <TextView + android:id="@+id/device_isDisplay" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="12sp"/> + +<!-- + <Button + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/connect" + android:id="@+id/button2"/> +--> + +</LinearLayout> diff --git a/app/src/main/res/menu/gatt_services.xml b/app/src/main/res/menu/gatt_services.xml new file mode 100644 index 0000000..25d64b6 --- /dev/null +++ b/app/src/main/res/menu/gatt_services.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_refresh" + android:checkable="false" + android:orderInCategory="1" + android:showAsAction="ifRoom"/> + <item android:id="@+id/menu_connect" + android:title="@string/menu_connect" + android:orderInCategory="100" + android:showAsAction="ifRoom|withText"/> + <item android:id="@+id/menu_disconnect" + android:title="@string/menu_disconnect" + android:orderInCategory="101" + android:showAsAction="ifRoom|withText"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml new file mode 100644 index 0000000..08b604e --- /dev/null +++ b/app/src/main/res/menu/main.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_refresh" + android:checkable="false" + android:orderInCategory="1" + android:showAsAction="ifRoom"/> + <item android:id="@+id/menu_scan" + android:title="@string/menu_scan" + android:orderInCategory="100" + android:showAsAction="ifRoom|withText"/> + <item android:id="@+id/menu_stop" + android:title="@string/menu_stop" + android:orderInCategory="101" + android:showAsAction="ifRoom|withText"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/menu_display_control.xml b/app/src/main/res/menu/menu_display_control.xml new file mode 100644 index 0000000..51a408b --- /dev/null +++ b/app/src/main/res/menu/menu_display_control.xml @@ -0,0 +1,8 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:context="no.topi.fiken.display.DisplayControlActivity"> + <item android:id="@+id/action_settings" + android:title="@string/action_settings" + android:orderInCategory="100" + android:showAsAction="never"/> +</menu> diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..87a750e --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,5 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> + <item android:id="@+id/action_settings" android:title="@string/action_settings" + android:orderInCategory="100" android:showAsAction="never" /> +</menu> diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ +<resources> + <!-- Example customization of dimensions originally defined in res/values/dimens.xml + (such as screen margins) for screens with more than 820dp of available width. This + would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> + <dimen name="activity_horizontal_margin">64dp</dimen> +</resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..47c8224 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ +<resources> + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> +</resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..0cea3b4 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name">Display</string> + <string name="hello_world">Hello world!</string> + <string name="action_settings">Settings</string> + <string name="ble_not_supported">BLE is not supported</string> + <string name="label_data">Data:</string> + <string name="label_device_address">Device address:</string> + <string name="label_state">State:</string> + <string name="no_data">No data</string> + <string name="connected">Connected</string> + <string name="disconnected">Disconnected</string> + <string name="title_devices">BLE Device Scan</string> + <string name="error_bluetooth_not_supported">Bluetooth not supported.</string> + <string name="unknown_device">Unknown device</string> + <string name="unknown_characteristic">Unknown characteristic</string> + <string name="unknown_service">Unknown service</string> + <string name="rssi">RSSI</string> + <string name="name_unknown">Unknown name</string> + <string name="rssi_unknown">unknown</string> + <string name="connect">Connect</string> + + <!-- Menu items --> + <string name="menu_connect">Connect</string> + <string name="menu_disconnect">Disconnect</string> + <string name="menu_scan">Scan</string> + <string name="menu_stop">Stop</string> + <string name="title_activity_display_control">DisplayControlActivity</string> + <string name="disconnect">Disconnect</string> + +</resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..ff6c9d2 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ +<resources> + + <!-- Base application theme. --> + <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> + <!-- Customize your theme here. --> + </style> + +</resources> diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..2e3fc3e --- /dev/null +++ b/build.gradle @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.13.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/fiken-display-android.iml b/fiken-display-android.iml new file mode 100644 index 0000000..0bb6048 --- /dev/null +++ b/fiken-display-android.iml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="java-gradle" name="Java-Gradle"> + <configuration> + <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <excludeFolder url="file://$MODULE_DIR$/.gradle" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..1d3591c --- /dev/null +++ b/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true
\ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 0000000..8c0fb64 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ffaa281 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app' |