commit
3344890caf
70 changed files with 3578 additions and 0 deletions
-
5.gitignore
-
192LICENSE
-
24README.md
-
32app/build.gradle
-
90app/src/main/AndroidManifest.xml
-
161app/src/main/java/com/google/android/glass/sample/apidemo/ApiDemoActivity.kt
-
59app/src/main/java/com/google/android/glass/sample/apidemo/card/CardAdapter.kt
-
163app/src/main/java/com/google/android/glass/sample/apidemo/card/CardBuilderActivity.kt
-
195app/src/main/java/com/google/android/glass/sample/apidemo/card/CardScrollViewActivity.kt
-
68app/src/main/java/com/google/android/glass/sample/apidemo/card/EmbeddedCardLayoutActivity.kt
-
121app/src/main/java/com/google/android/glass/sample/apidemo/card/EmbeddedCardLayoutAdapter.kt
-
34app/src/main/java/com/google/android/glass/sample/apidemo/card/SimpleTableItem.kt
-
159app/src/main/java/com/google/android/glass/sample/apidemo/opengl/Cube.kt
-
100app/src/main/java/com/google/android/glass/sample/apidemo/opengl/CubeRenderer.kt
-
67app/src/main/java/com/google/android/glass/sample/apidemo/opengl/MenuActivity.kt
-
64app/src/main/java/com/google/android/glass/sample/apidemo/opengl/OpenGlService.kt
-
176app/src/main/java/com/google/android/glass/sample/apidemo/slider/SliderActivity.kt
-
47app/src/main/java/com/google/android/glass/sample/apidemo/theming/TextAppearanceActivity.kt
-
63app/src/main/java/com/google/android/glass/sample/apidemo/theming/TextAppearanceAdapter.kt
-
89app/src/main/java/com/google/android/glass/sample/apidemo/touchpad/ContinuousGesturesActivity.kt
-
87app/src/main/java/com/google/android/glass/sample/apidemo/touchpad/DiscreteGesturesActivity.kt
-
100app/src/main/java/com/google/android/glass/sample/apidemo/touchpad/SelectGestureDemoActivity.kt
-
238app/src/main/java/com/google/android/glass/sample/apidemo/touchpad/TouchpadView.kt
-
143app/src/main/java/com/google/android/glass/sample/apidemo/voicemenu/VoiceMenuActivity.kt
-
BINapp/src/main/res/drawable-hdpi/ic_avatar_70.png
-
BINapp/src/main/res/drawable-hdpi/ic_circle_blue.png
-
BINapp/src/main/res/drawable-hdpi/ic_circle_green.png
-
BINapp/src/main/res/drawable-hdpi/ic_circle_red.png
-
BINapp/src/main/res/drawable-hdpi/ic_circle_yellow.png
-
BINapp/src/main/res/drawable-hdpi/ic_glass_logo.png
-
BINapp/src/main/res/drawable-hdpi/ic_phone_50.png
-
BINapp/src/main/res/drawable-hdpi/ic_smile.png
-
BINapp/src/main/res/drawable-hdpi/ic_stop.png
-
BINapp/src/main/res/drawable-hdpi/ic_warning_150.png
-
BINapp/src/main/res/drawable-hdpi/ic_wifi_150.png
-
BINapp/src/main/res/drawable/beach.jpg
-
BINapp/src/main/res/drawable/codemonkey1.jpg
-
BINapp/src/main/res/drawable/codemonkey2.jpg
-
BINapp/src/main/res/drawable/codemonkey3.jpg
-
BINapp/src/main/res/drawable/codemonkey4.jpg
-
BINapp/src/main/res/drawable/codemonkey5.jpg
-
BINapp/src/main/res/drawable/codemonkey6.jpg
-
BINapp/src/main/res/drawable/codemonkey7.jpg
-
BINapp/src/main/res/drawable/codemonkey8.jpg
-
BINapp/src/main/res/drawable/designer.jpg
-
20app/src/main/res/drawable/finger_trace_0.xml
-
20app/src/main/res/drawable/finger_trace_1.xml
-
20app/src/main/res/drawable/finger_trace_2.xml
-
BINapp/src/main/res/drawable/product.jpg
-
32app/src/main/res/drawable/table_row_divider.xml
-
142app/src/main/res/layout/activity_continuous_gestures.xml
-
95app/src/main/res/layout/activity_discrete_gestures.xml
-
32app/src/main/res/layout/simple_table.xml
-
46app/src/main/res/layout/simple_table_row.xml
-
39app/src/main/res/layout/text_appearances_large.xml
-
39app/src/main/res/layout/text_appearances_medium.xml
-
39app/src/main/res/layout/text_appearances_small.xml
-
22app/src/main/res/menu/opengl_livecard.xml
-
55app/src/main/res/menu/voice_menu.xml
-
32app/src/main/res/values/colors.xml
-
23app/src/main/res/values/dimens.xml
-
118app/src/main/res/values/string.xml
-
26app/src/main/res/values/styles.xml
-
17app/src/main/res/xml/voice_trigger.xml
-
23build.gradle
-
BINgradle/wrapper/gradle-wrapper.jar
-
6gradle/wrapper/gradle-wrapper.properties
-
164gradlew
-
90gradlew.bat
-
1settings.gradle
@ -0,0 +1,5 @@ |
|||
*.iml |
|||
local.properties |
|||
.idea/ |
|||
.gradle/ |
|||
build/ |
@ -0,0 +1,192 @@ |
|||
Apache License |
|||
Version 2.0, January 2004 |
|||
http://www.apache.org/licenses/ |
|||
|
|||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, and |
|||
distribution as defined by Sections 1 through 9 of this document. |
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by the copyright |
|||
owner that is granting the License. |
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all other entities |
|||
that control, are controlled by, or are under common control with that entity. |
|||
For the purposes of this definition, "control" means (i) the power, direct or |
|||
indirect, to cause the direction or management of such entity, whether by |
|||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|||
outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity exercising |
|||
permissions granted by this License. |
|||
|
|||
"Source" form shall mean the preferred form for making modifications, including |
|||
but not limited to software source code, documentation source, and configuration |
|||
files. |
|||
|
|||
"Object" form shall mean any form resulting from mechanical transformation or |
|||
translation of a Source form, including but not limited to compiled object code, |
|||
generated documentation, and conversions to other media types. |
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or Object form, made |
|||
available under the License, as indicated by a copyright notice that is included |
|||
in or attached to the work (an example is provided in the Appendix below). |
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object form, that |
|||
is based on (or derived from) the Work and for which the editorial revisions, |
|||
annotations, elaborations, or other modifications represent, as a whole, an |
|||
original work of authorship. For the purposes of this License, Derivative Works |
|||
shall not include works that remain separable from, or merely link (or bind by |
|||
name) to the interfaces of, the Work and Derivative Works thereof. |
|||
|
|||
"Contribution" shall mean any work of authorship, including the original version |
|||
of the Work and any modifications or additions to that Work or Derivative Works |
|||
thereof, that is intentionally submitted to Licensor for inclusion in the Work |
|||
by the copyright owner or by an individual or Legal Entity authorized to submit |
|||
on behalf of the copyright owner. For the purposes of this definition, |
|||
"submitted" means any form of electronic, verbal, or written communication sent |
|||
to the Licensor or its representatives, including but not limited to |
|||
communication on electronic mailing lists, source code control systems, and |
|||
issue tracking systems that are managed by, or on behalf of, the Licensor for |
|||
the purpose of discussing and improving the Work, but excluding communication |
|||
that is conspicuously marked or otherwise designated in writing by the copyright |
|||
owner as "Not a Contribution." |
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf |
|||
of whom a Contribution has been received by Licensor and subsequently |
|||
incorporated within the Work. |
|||
|
|||
2. Grant of Copyright License. |
|||
|
|||
Subject to the terms and conditions of this License, each Contributor hereby |
|||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, |
|||
irrevocable copyright license to reproduce, prepare Derivative Works of, |
|||
publicly display, publicly perform, sublicense, and distribute the Work and such |
|||
Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. |
|||
|
|||
Subject to the terms and conditions of this License, each Contributor hereby |
|||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, |
|||
irrevocable (except as stated in this section) patent license to make, have |
|||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where |
|||
such license applies only to those patent claims licensable by such Contributor |
|||
that are necessarily infringed by their Contribution(s) alone or by combination |
|||
of their Contribution(s) with the Work to which such Contribution(s) was |
|||
submitted. If You institute patent litigation against any entity (including a |
|||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a |
|||
Contribution incorporated within the Work constitutes direct or contributory |
|||
patent infringement, then any patent licenses granted to You under this License |
|||
for that Work shall terminate as of the date such litigation is filed. |
|||
|
|||
4. Redistribution. |
|||
|
|||
You may reproduce and distribute copies of the Work or Derivative Works thereof |
|||
in any medium, with or without modifications, and in Source or Object form, |
|||
provided that You meet the following conditions: |
|||
|
|||
You must give any other recipients of the Work or Derivative Works a copy of |
|||
this License; and |
|||
You must cause any modified files to carry prominent notices stating that You |
|||
changed the files; and |
|||
You must retain, in the Source form of any Derivative Works that You distribute, |
|||
all copyright, patent, trademark, and attribution notices from the Source form |
|||
of the Work, excluding those notices that do not pertain to any part of the |
|||
Derivative Works; and |
|||
If the Work includes a "NOTICE" text file as part of its distribution, then any |
|||
Derivative Works that You distribute must include a readable copy of the |
|||
attribution notices contained within such NOTICE file, excluding those notices |
|||
that do not pertain to any part of the Derivative Works, in at least one of the |
|||
following places: within a NOTICE text file distributed as part of the |
|||
Derivative Works; within the Source form or documentation, if provided along |
|||
with the Derivative Works; or, within a display generated by the Derivative |
|||
Works, if and wherever such third-party notices normally appear. The contents of |
|||
the NOTICE file are for informational purposes only and do not modify the |
|||
License. You may add Your own attribution notices within Derivative Works that |
|||
You distribute, alongside or as an addendum to the NOTICE text from the Work, |
|||
provided that such additional attribution notices cannot be construed as |
|||
modifying the License. |
|||
You may add Your own copyright statement to Your modifications and may provide |
|||
additional or different license terms and conditions for use, reproduction, or |
|||
distribution of Your modifications, or for any such Derivative Works as a whole, |
|||
provided Your use, reproduction, and distribution of the Work otherwise complies |
|||
with the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. |
|||
|
|||
Unless You explicitly state otherwise, any Contribution intentionally submitted |
|||
for inclusion in the Work by You to the Licensor shall be under the terms and |
|||
conditions of this License, without any additional terms or conditions. |
|||
Notwithstanding the above, nothing herein shall supersede or modify the terms of |
|||
any separate license agreement you may have executed with Licensor regarding |
|||
such Contributions. |
|||
|
|||
6. Trademarks. |
|||
|
|||
This License does not grant permission to use the trade names, trademarks, |
|||
service marks, or product names of the Licensor, except as required for |
|||
reasonable and customary use in describing the origin of the Work and |
|||
reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. |
|||
|
|||
Unless required by applicable law or agreed to in writing, Licensor provides the |
|||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, |
|||
including, without limitation, any warranties or conditions of TITLE, |
|||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are |
|||
solely responsible for determining the appropriateness of using or |
|||
redistributing the Work and assume any risks associated with Your exercise of |
|||
permissions under this License. |
|||
|
|||
8. Limitation of Liability. |
|||
|
|||
In no event and under no legal theory, whether in tort (including negligence), |
|||
contract, or otherwise, unless required by applicable law (such as deliberate |
|||
and grossly negligent acts) or agreed to in writing, shall any Contributor be |
|||
liable to You for damages, including any direct, indirect, special, incidental, |
|||
or consequential damages of any character arising as a result of this License or |
|||
out of the use or inability to use the Work (including but not limited to |
|||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or |
|||
any and all other commercial damages or losses), even if such Contributor has |
|||
been advised of the possibility of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. |
|||
|
|||
While redistributing the Work or Derivative Works thereof, You may choose to |
|||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or |
|||
other liability obligations and/or rights consistent with this License. However, |
|||
in accepting such obligations, You may act only on Your own behalf and on Your |
|||
sole responsibility, not on behalf of any other Contributor, and only if You |
|||
agree to indemnify, defend, and hold each Contributor harmless for any liability |
|||
incurred by, or claims asserted against, such Contributor by reason of your |
|||
accepting any such warranty or additional liability. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work |
|||
|
|||
To apply the Apache License to your work, attach the following boilerplate |
|||
notice, with the fields enclosed by brackets "[]" replaced with your own |
|||
identifying information. (Don't include the brackets!) The text should be |
|||
enclosed in the appropriate comment syntax for the file format. We also |
|||
recommend that a file or class name and description of purpose be included on |
|||
the same "printed page" as the copyright notice for easier identification within |
|||
third-party archives. |
|||
|
|||
Copyright [yyyy] [name of copyright owner] |
|||
|
|||
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. |
|||
|
@ -0,0 +1,24 @@ |
|||
ApiDemo |
|||
======= |
|||
|
|||
This sample is a gallery of some GDK APIs usage rewritten in Kotlin: |
|||
|
|||
- Card and CardScrollView |
|||
- GestureDetector |
|||
- Theming with textAppearance |
|||
- OpenGL in a LiveCard |
|||
|
|||
## Getting started |
|||
|
|||
Check out our documentation to learn how to get started on |
|||
https://developers.google.com/glass/gdk/index |
|||
|
|||
## Running the sample on Glass |
|||
|
|||
On the command line: |
|||
|
|||
$ ./gradlew clean build |
|||
$ adb install -r app/build/outputs/apk/debug/app-debug.apk |
|||
|
|||
To start the sample, say "ok glass, show me a demo" from the Glass clock |
|||
screen. |
@ -0,0 +1,32 @@ |
|||
apply plugin: 'com.android.application' |
|||
apply plugin: 'kotlin-android' |
|||
apply plugin: 'kotlin-android-extensions' |
|||
|
|||
|
|||
repositories { |
|||
jcenter() |
|||
flatDir { |
|||
dirs 'prebuilt-libs' |
|||
} |
|||
} |
|||
|
|||
android { |
|||
compileSdkVersion "Google Inc.:Glass Development Kit Preview:19" |
|||
buildToolsVersion "28.0.3" |
|||
|
|||
defaultConfig { |
|||
minSdkVersion 19 |
|||
targetSdkVersion 28 |
|||
} |
|||
buildTypes { |
|||
release { |
|||
minifyEnabled true |
|||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
|||
} |
|||
} |
|||
} |
|||
|
|||
dependencies { |
|||
implementation fileTree(dir: 'libs', include: ['*.jar']) |
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" |
|||
} |
@ -0,0 +1,90 @@ |
|||
<?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. |
|||
--> |
|||
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
|||
package="com.google.android.glass.sample.apidemo" |
|||
android:versionCode="1" |
|||
android:versionName="1.0" |
|||
> |
|||
|
|||
<!-- For free-style voice trigger and voice menus. --> |
|||
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT"/> |
|||
|
|||
<uses-feature android:glEsVersion="0x00020000" android:required="true" /> |
|||
|
|||
<application> |
|||
|
|||
<activity android:name=".ApiDemoActivity" |
|||
android:icon="@drawable/ic_glass_logo" |
|||
android:label="@string/app_name" |
|||
android:exported="true" > |
|||
<intent-filter> |
|||
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" /> |
|||
</intent-filter> |
|||
<meta-data android:name="com.google.android.glass.VoiceTrigger" |
|||
android:resource="@xml/voice_trigger" |
|||
/> |
|||
</activity> |
|||
|
|||
<activity android:name=".card.CardBuilderActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".card.EmbeddedCardLayoutActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".card.CardScrollViewActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".touchpad.SelectGestureDemoActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".touchpad.DiscreteGesturesActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".touchpad.ContinuousGesturesActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".theming.TextAppearanceActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".opengl.MenuActivity" |
|||
android:exported="true" |
|||
android:theme="@style/MenuTheme" |
|||
/> |
|||
|
|||
<service |
|||
android:name=".opengl.OpenGlService" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".voicemenu.VoiceMenuActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
<activity android:name=".slider.SliderActivity" |
|||
android:exported="true" |
|||
/> |
|||
|
|||
</application> |
|||
|
|||
</manifest> |
@ -0,0 +1,161 @@ |
|||
/* |
|||
* 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo |
|||
|
|||
import com.google.android.glass.media.Sounds |
|||
import com.google.android.glass.sample.apidemo.card.CardAdapter |
|||
import com.google.android.glass.sample.apidemo.card.CardBuilderActivity |
|||
import com.google.android.glass.sample.apidemo.card.CardScrollViewActivity |
|||
import com.google.android.glass.sample.apidemo.card.EmbeddedCardLayoutActivity |
|||
import com.google.android.glass.sample.apidemo.opengl.OpenGlService |
|||
import com.google.android.glass.sample.apidemo.slider.SliderActivity |
|||
import com.google.android.glass.sample.apidemo.theming.TextAppearanceActivity |
|||
import com.google.android.glass.sample.apidemo.touchpad.SelectGestureDemoActivity |
|||
import com.google.android.glass.sample.apidemo.voicemenu.VoiceMenuActivity |
|||
import com.google.android.glass.widget.CardBuilder |
|||
import com.google.android.glass.widget.CardScrollAdapter |
|||
import com.google.android.glass.widget.CardScrollView |
|||
|
|||
import android.app.Activity |
|||
import android.content.Context |
|||
import android.content.Intent |
|||
import android.media.AudioManager |
|||
import android.os.Bundle |
|||
import android.util.Log |
|||
import android.widget.AdapterView |
|||
|
|||
import java.util.ArrayList |
|||
|
|||
/** |
|||
* Creates a card scroll view with examples of different GDK APIs. |
|||
* |
|||
* |
|||
* 1. CardBuilder API |
|||
* 1. CardScrollView API |
|||
* 1. GestureDetector |
|||
* 1. textAppearance[Large|Medium|Small] |
|||
* 1. OpenGL LiveCard |
|||
* 1. VoiceMenu |
|||
* |
|||
*/ |
|||
class ApiDemoActivity : Activity() { |
|||
|
|||
private lateinit var mAdapter: CardScrollAdapter |
|||
// Visible for testing. |
|||
private lateinit var scroller: CardScrollView |
|||
|
|||
override fun onCreate(bundle: Bundle?) { |
|||
super.onCreate(bundle) |
|||
|
|||
mAdapter = CardAdapter(createCards(this)) |
|||
print("CARDS CREATED ${mAdapter.count}") |
|||
scroller = CardScrollView(this) |
|||
scroller.adapter = mAdapter |
|||
setContentView(scroller) |
|||
setCardScrollerListener() |
|||
} |
|||
|
|||
/** |
|||
* Create list of API demo cards. |
|||
*/ |
|||
private fun createCards(context: Context): MutableList<CardBuilder> { |
|||
val cards = ArrayList<CardBuilder>() |
|||
cards.add(CARD_BUILDER, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_builder)) |
|||
cards.add(CARD_BUILDER_EMBEDDED_LAYOUT, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_builder_embedded_layout)) |
|||
cards.add(CARD_SCROLL_VIEW, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_scroll_view)) |
|||
cards.add(GESTURE_DETECTOR, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_gesture_detector)) |
|||
cards.add(TEXT_APPEARANCE, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_text_appearance)) |
|||
cards.add(OPENGL, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_opengl)) |
|||
cards.add(VOICE_MENU, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_voice_menu)) |
|||
cards.add(SLIDER, CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_slider)) |
|||
return cards |
|||
} |
|||
|
|||
override fun onResume() { |
|||
super.onResume() |
|||
scroller.activate() |
|||
} |
|||
|
|||
override fun onPause() { |
|||
scroller.deactivate() |
|||
super.onPause() |
|||
} |
|||
|
|||
/** |
|||
* Different type of activities can be shown, when tapped on a card. |
|||
*/ |
|||
private fun setCardScrollerListener() { |
|||
scroller.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, id -> |
|||
Log.d(TAG, "Clicked view at position $position, row-id $id") |
|||
var soundEffect = Sounds.TAP |
|||
when (position) { |
|||
CARD_BUILDER -> startActivity(Intent(this@ApiDemoActivity, CardBuilderActivity::class.java)) |
|||
|
|||
CARD_BUILDER_EMBEDDED_LAYOUT -> startActivity(Intent( |
|||
this@ApiDemoActivity, EmbeddedCardLayoutActivity::class.java)) |
|||
|
|||
CARD_SCROLL_VIEW -> startActivity(Intent(this@ApiDemoActivity, |
|||
CardScrollViewActivity::class.java)) |
|||
|
|||
GESTURE_DETECTOR -> startActivity(Intent(this@ApiDemoActivity, |
|||
SelectGestureDemoActivity::class.java)) |
|||
|
|||
TEXT_APPEARANCE -> startActivity(Intent(this@ApiDemoActivity, |
|||
TextAppearanceActivity::class.java)) |
|||
|
|||
OPENGL -> startService(Intent(this@ApiDemoActivity, OpenGlService::class.java)) |
|||
|
|||
VOICE_MENU -> startActivity(Intent(this@ApiDemoActivity, VoiceMenuActivity::class.java)) |
|||
|
|||
SLIDER -> startActivity(Intent(this@ApiDemoActivity, SliderActivity::class.java)) |
|||
|
|||
else -> { |
|||
soundEffect = Sounds.ERROR |
|||
Log.d(TAG, "Don't show anything") |
|||
} |
|||
} |
|||
|
|||
// Play sound. |
|||
val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager |
|||
am.playSoundEffect(soundEffect) |
|||
} |
|||
} |
|||
|
|||
companion object { |
|||
|
|||
private val TAG = ApiDemoActivity::class.java.simpleName |
|||
|
|||
// Index of api demo cards. |
|||
// Visible for testing. |
|||
internal const val CARD_BUILDER = 0 |
|||
internal const val CARD_BUILDER_EMBEDDED_LAYOUT = 1 |
|||
internal const val CARD_SCROLL_VIEW = 2 |
|||
internal const val GESTURE_DETECTOR = 3 |
|||
internal const val TEXT_APPEARANCE = 4 |
|||
internal const val OPENGL = 5 |
|||
internal const val VOICE_MENU = 6 |
|||
internal const val SLIDER = 7 |
|||
} |
|||
} |
@ -0,0 +1,59 @@ |
|||
/* |
|||
* 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
import com.google.android.glass.widget.CardBuilder |
|||
import com.google.android.glass.widget.CardScrollAdapter |
|||
|
|||
import android.view.View |
|||
import android.view.ViewGroup |
|||
import android.widget.AdapterView |
|||
|
|||
/** |
|||
* Adapter class that handles list of cards. |
|||
*/ |
|||
open class CardAdapter(internal val mCards: MutableList<CardBuilder>) : CardScrollAdapter() { |
|||
|
|||
override fun getCount(): Int { |
|||
return mCards.size |
|||
} |
|||
|
|||
override fun getItem(position: Int): Any { |
|||
return mCards[position] |
|||
} |
|||
|
|||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { |
|||
return mCards[position].getView(convertView, parent) |
|||
} |
|||
|
|||
override fun getViewTypeCount(): Int { |
|||
return CardBuilder.getViewTypeCount() |
|||
} |
|||
|
|||
override fun getItemViewType(position: Int): Int { |
|||
return mCards[position].itemViewType |
|||
} |
|||
|
|||
override fun getPosition(item: Any): Int { |
|||
for (i in mCards.indices) { |
|||
if (getItem(i) == item) { |
|||
return i |
|||
} |
|||
} |
|||
return AdapterView.INVALID_POSITION |
|||
} |
|||
} |
@ -0,0 +1,163 @@ |
|||
/* |
|||
* 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
import com.google.android.glass.sample.apidemo.R |
|||
import com.google.android.glass.widget.CardBuilder |
|||
import com.google.android.glass.widget.CardScrollView |
|||
|
|||
import android.app.Activity |
|||
import android.content.Context |
|||
import android.os.Bundle |
|||
|
|||
import java.util.ArrayList |
|||
|
|||
/** |
|||
* Creates a card scroll view with examples of different image layout cards. |
|||
*/ |
|||
class CardBuilderActivity : Activity() { |
|||
|
|||
private lateinit var mCardScroller: CardScrollView |
|||
|
|||
override fun onCreate(bundle: Bundle?) { |
|||
super.onCreate(bundle) |
|||
mCardScroller = CardScrollView(this) |
|||
mCardScroller.adapter = CardAdapter(createCards(this)) |
|||
setContentView(mCardScroller) |
|||
} |
|||
|
|||
/** |
|||
* Creates list of cards that showcase different type of [CardBuilder] API. |
|||
*/ |
|||
private fun createCards(context: Context): MutableList<CardBuilder> { |
|||
val cards = ArrayList<CardBuilder>() |
|||
|
|||
// Add cards that demonstrate TEXT layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_text_not_fixed) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(createCardWithImages(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_text_with_images) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.TEXT_FIXED) |
|||
.setText(R.string.text_card_text_fixed) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.TEXT) |
|||
.setText(R.string.text_card_text_stack_indicator) |
|||
.showStackIndicator(true) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
|
|||
// Add cards that demonstrate COLUMNS layouts. |
|||
cards.add(createCardWithImages(context, CardBuilder.Layout.COLUMNS) |
|||
.setText(R.string.text_card_columns_not_fixed) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.COLUMNS) |
|||
.setText(R.string.text_card_columns_with_icon) |
|||
.setIcon(R.drawable.ic_wifi_150) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(createCardWithImages(context, CardBuilder.Layout.COLUMNS) |
|||
.setText(R.string.text_card_columns_fixed) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
|
|||
// Add cards that demonstrate CAPTION layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.CAPTION) |
|||
.addImage(R.drawable.beach) |
|||
.setText(R.string.text_card_caption) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.CAPTION) |
|||
.addImage(R.drawable.beach) |
|||
.setText(R.string.text_card_caption_with_icon) |
|||
.setIcon(R.drawable.ic_avatar_70) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
|
|||
// Add cards that demonstrate TITLE layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.TITLE) |
|||
.addImage(R.drawable.beach) |
|||
.setText(R.string.text_card_title)) |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.TITLE) |
|||
.addImage(R.drawable.beach) |
|||
.setText(R.string.text_card_title_icon) |
|||
.setIcon(R.drawable.ic_phone_50)) |
|||
|
|||
// Add cards that demonstrate MENU layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.MENU) |
|||
.setText(R.string.text_card_menu) |
|||
.setFootnote(R.string.text_card_menu_description) |
|||
.setIcon(R.drawable.ic_phone_50)) |
|||
|
|||
// Add cards that demonstrate ALERT layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.ALERT) |
|||
.setText(R.string.text_card_alert) |
|||
.setFootnote(R.string.text_card_alert_description) |
|||
.setIcon(R.drawable.ic_warning_150)) |
|||
|
|||
// Add cards that demonstrate AUTHOR layouts. |
|||
cards.add(CardBuilder(context, CardBuilder.Layout.AUTHOR) |
|||
.setText(R.string.text_card_author_text) |
|||
.setIcon(R.drawable.ic_avatar_70) |
|||
.setHeading(R.string.text_card_author_heading) |
|||
.setSubheading(R.string.text_card_author_subheading) |
|||
.setFootnote(R.string.text_card_footnote) |
|||
.setTimestamp(R.string.text_card_timestamp) |
|||
.setAttributionIcon(R.drawable.ic_smile)) |
|||
|
|||
return cards |
|||
} |
|||
|
|||
/** |
|||
* Returns a new [CardBuilder] with the specified layout and adds five images to it for |
|||
* the mosaic. |
|||
*/ |
|||
private fun createCardWithImages(context: Context, layout: CardBuilder.Layout): CardBuilder { |
|||
val card = CardBuilder(context, layout) |
|||
card.addImage(R.drawable.codemonkey1) |
|||
card.addImage(R.drawable.codemonkey2) |
|||
card.addImage(R.drawable.codemonkey3) |
|||
card.addImage(R.drawable.codemonkey4) |
|||
card.addImage(R.drawable.codemonkey5) |
|||
card.addImage(R.drawable.codemonkey6) |
|||
card.addImage(R.drawable.codemonkey7) |
|||
card.addImage(R.drawable.codemonkey8) |
|||
return card |
|||
} |
|||
|
|||
override fun onResume() { |
|||
super.onResume() |
|||
mCardScroller.activate() |
|||
} |
|||
|
|||
override fun onPause() { |
|||
mCardScroller.deactivate() |
|||
super.onPause() |
|||
} |
|||
} |
@ -0,0 +1,195 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
import com.google.android.glass.media.Sounds |
|||
import com.google.android.glass.sample.apidemo.R |
|||
import com.google.android.glass.widget.CardBuilder |
|||
import com.google.android.glass.widget.CardScrollView |
|||
|
|||
import android.app.Activity |
|||
import android.content.Context |
|||
import android.media.AudioManager |
|||
import android.os.Bundle |
|||
import android.widget.AdapterView |
|||
|
|||
import java.util.ArrayList |
|||
import java.util.Random |
|||
|
|||
/** |
|||
* Creates a card scroll view with various examples of its API. |
|||
*/ |
|||
class CardScrollViewActivity : Activity() { |
|||
|
|||
private val mRandom = Random() |
|||
|
|||
private var mCardScroller: CardScrollView? = null |
|||
private var mAdapter: CardAdapterWithMutations? = null |
|||
|
|||
/** Actions associated with cards. */ |
|||
private enum class Action constructor(internal val textId: Int, internal val imageId: Int) { |
|||
DELETION_HERE(R.string.text_card_tap_to_delete, R.drawable.codemonkey1), |
|||
NAVIGATION_TO_BEGIN(R.string.text_card_tap_to_navigate_begin, R.drawable.codemonkey2), |
|||
NAVIGATION_TO_END(R.string.text_card_tap_to_navigate_end, R.drawable.codemonkey3), |
|||
INSERTION_AT_BEGIN(R.string.text_card_tap_to_insert_begin, R.drawable.codemonkey4), |
|||
INSERTION_BEFORE(R.string.text_card_tap_to_insert_before, R.drawable.codemonkey5), |
|||
INSERTION_AFTER(R.string.text_card_tap_to_insert_after, R.drawable.codemonkey6), |
|||
INSERTION_AT_END(R.string.text_card_tap_to_insert_end, R.drawable.codemonkey7), |
|||
NO_ACTION(R.string.text_card_no_action, R.drawable.codemonkey8) |
|||
} |
|||
|
|||
/** |
|||
* Adapter class that handles list of cards with associated actions and |
|||
* allows for mutations without notifying the adapter of the data change yet |
|||
* (through method [.notifyDataSetChanged]). Useful to demonstrate |
|||
* mutation animations. |
|||
*/ |
|||
private inner class CardAdapterWithMutations : CardAdapter(ArrayList()) { |
|||
|
|||
private val mActions: MutableList<Action> |
|||
|
|||
init { |
|||
mActions = ArrayList() |
|||
} |
|||
|
|||
/** Inserts a card into the adapter, without notifying. */ |
|||
fun insertCardWithoutNotification(position: Int, card: CardBuilder, action: Action) { |
|||
mCards.add(position, card) |
|||
mActions.add(position, action) |
|||
} |
|||
|
|||
/** Deletes card from the adapter, without notifying. */ |
|||
fun deleteCardWithoutNotification(position: Int) { |
|||
mCards.removeAt(position) |
|||
mActions.removeAt(position) |
|||
} |
|||
|
|||
/** Returns the action associated with the card at position. */ |
|||
fun getActionAt(position: Int): Action { |
|||
return mActions[position] |
|||
} |
|||
} |
|||
|
|||
override fun onCreate(bundle: Bundle?) { |
|||
super.onCreate(bundle) |
|||
|
|||
mCardScroller = CardScrollView(this) |
|||
setupAdapter() |
|||
setupClickListener() |
|||
setContentView(mCardScroller) |
|||
} |
|||
|
|||
/** |
|||
* Sets up adapter. |
|||
*/ |
|||
private fun setupAdapter() { |
|||
mAdapter = CardAdapterWithMutations() |
|||
|
|||
// Insert initial cards, one of each kind. |
|||
for (i in 0..7) { |
|||
val action = Action.values()[i] |
|||
val card = CardBuilder(this, CardBuilder.Layout.COLUMNS) |
|||
card.setText(action.textId).addImage(action.imageId) |
|||
mAdapter!!.insertCardWithoutNotification(i, card, action) |
|||
} |
|||
|
|||
// Setting adapter notifies the card scroller of new content. |
|||
mCardScroller!!.adapter = mAdapter |
|||
} |
|||
|
|||
/** |
|||
* Sets up click listener. |
|||
*/ |
|||
private fun setupClickListener() { |
|||
mCardScroller!!.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> |
|||
val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager |
|||
when (mAdapter!!.getActionAt(position)) { |
|||
Action.DELETION_HERE -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
deleteCard(position) |
|||
} |
|||
Action.NAVIGATION_TO_BEGIN -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
navigateToCard(0) |
|||
} |
|||
Action.NAVIGATION_TO_END -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
navigateToCard(mAdapter!!.count - 1) |
|||
} |
|||
Action.INSERTION_AT_BEGIN -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
insertNewCard(0) |
|||
} |
|||
Action.INSERTION_BEFORE -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
insertNewCard(position) |
|||
} |
|||
Action.INSERTION_AFTER -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
insertNewCard(position + 1) |
|||
} |
|||
Action.INSERTION_AT_END -> { |
|||
am.playSoundEffect(Sounds.TAP) |
|||
insertNewCard(mAdapter!!.count) |
|||
} |
|||
else -> am.playSoundEffect(Sounds.DISALLOWED) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Deletes a card at the given position using proper insertion animation |
|||
* (the card scroller will animate the old card from view). |
|||
*/ |
|||
private fun deleteCard(position: Int) { |
|||
// Delete card in the adapter, but don't call notifyDataSetChanged() yet. |
|||
// Instead, request proper animation for deleted card from card scroller, |
|||
// which will notify the adapter at the right time during the animation. |
|||
mAdapter!!.deleteCardWithoutNotification(position) |
|||
mCardScroller!!.animate(position, CardScrollView.Animation.DELETION) |
|||
} |
|||
|
|||
/** Navigates to card at given position. */ |
|||
private fun navigateToCard(position: Int) { |
|||
mCardScroller!!.animate(position, CardScrollView.Animation.NAVIGATION) |
|||
} |
|||
|
|||
/** |
|||
* Inserts a new card at the given position using proper insertion animation |
|||
* (the card scroller will animate to the new card). |
|||
*/ |
|||
private fun insertNewCard(position: Int) { |
|||
// Insert new card in the adapter, but don't call notifyDataSetChanged() |
|||
// yet. Instead, request proper animation to inserted card from card scroller, |
|||
// which will notify the adapter at the right time during the animation. |
|||
val card = CardBuilder(this, CardBuilder.Layout.COLUMNS) |
|||
val action = Action.values()[mRandom.nextInt(8)] |
|||
card.setText(action.textId).addImage(action.imageId) |
|||
mAdapter!!.insertCardWithoutNotification(position, card, action) |
|||
mCardScroller!!.animate(position, CardScrollView.Animation.INSERTION) |
|||
} |
|||
|
|||
override fun onResume() { |
|||
super.onResume() |
|||
mCardScroller!!.activate() |
|||
} |
|||
|
|||
override fun onPause() { |
|||
mCardScroller!!.deactivate() |
|||
super.onPause() |
|||
} |
|||
} |
@ -0,0 +1,68 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
import com.google.android.glass.sample.apidemo.R |
|||
import com.google.android.glass.widget.CardScrollView |
|||
|
|||
import android.app.Activity |
|||
import android.os.Bundle |
|||
|
|||
import java.util.ArrayList |
|||
|
|||
/** |
|||
* Creates a card scroll view that shows an example of using a custom embedded layout in a |
|||
* `CardBuilder`. |
|||
*/ |
|||
class EmbeddedCardLayoutActivity : Activity() { |
|||
|
|||
private lateinit var mCardScroller: CardScrollView |
|||
|
|||
override fun onCreate(bundle: Bundle?) { |
|||
super.onCreate(bundle) |
|||
mCardScroller = CardScrollView(this) |
|||
mCardScroller.adapter = EmbeddedCardLayoutAdapter(this, createItems()) |
|||
setContentView(mCardScroller) |
|||
} |
|||
|
|||
/** Creates some sample items that will be displayed on cards in the card scroll view. */ |
|||
private fun createItems(): List<SimpleTableItem> { |
|||
val items = ArrayList<SimpleTableItem>() |
|||
|
|||
items.add(SimpleTableItem(R.drawable.ic_circle_blue, "Water", "8 oz")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_yellow, "Eggs, large", "2")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_red, "Ground beef", "4 oz")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_green, "Brussel sprouts", "1 cup")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_green, "Celery", "1 stalk")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_red, "Beef jerky", "8 strips")) |
|||
items.add(SimpleTableItem(R.drawable.ic_circle_yellow, "Almonds", "3 handfuls")) |
|||
items.add(SimpleTableItem( |
|||
R.drawable.ic_circle_red, "Strawberry fruit leather", "2.5 miles")) |
|||
|
|||
return items |
|||
} |
|||
|
|||
override fun onResume() { |
|||
super.onResume() |
|||
mCardScroller.activate() |
|||
} |
|||
|
|||
override fun onPause() { |
|||
mCardScroller.deactivate() |
|||
super.onPause() |
|||
} |
|||
} |
@ -0,0 +1,121 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
import com.google.android.glass.sample.apidemo.R |
|||
import com.google.android.glass.widget.CardBuilder |
|||
import com.google.android.glass.widget.CardScrollAdapter |
|||
|
|||
import android.content.Context |
|||
import android.view.View |
|||
import android.view.ViewGroup |
|||
import android.widget.AdapterView |
|||
import android.widget.ImageView |
|||
import android.widget.TextView |
|||
|
|||
/** |
|||
* Populates views in a `CardScrollView` with cards built from custom embedded layouts to |
|||
* represent items in a simple table. |
|||
*/ |
|||
class EmbeddedCardLayoutAdapter |
|||
/** Initializes a new adapter with the specified context and list of items. */ |
|||
(private val mContext: Context, private val mItems: List<SimpleTableItem>) : CardScrollAdapter() { |
|||
|
|||
override fun getViewTypeCount(): Int { |
|||
return 1 |
|||
} |
|||
|
|||
override fun getItemViewType(position: Int): Int { |
|||
return 0 |
|||
} |
|||
|
|||
override fun getCount(): Int { |
|||
// Compute the number of cards needed to display the items with 4 per card (rounding up to |
|||
// capture the remainder). |
|||
return Math.ceil(mItems.size.toDouble() / ITEMS_PER_CARD).toInt() |
|||
} |
|||
|
|||
override fun getItem(position: Int): Any? { |
|||
return null |
|||
} |
|||
|
|||
override fun getPosition(item: Any): Int { |
|||
return AdapterView.INVALID_POSITION |
|||
} |
|||
|
|||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { |
|||
val card = CardBuilder(mContext, CardBuilder.Layout.EMBED_INSIDE) |
|||
.setEmbeddedLayout(R.layout.simple_table) |
|||
.setFootnote(R.string.text_card_embedded_footnote) |
|||
.setTimestamp(R.string.text_card_embedded_timestamp) |
|||
val view = card.getView(convertView, parent) |
|||
|
|||
// Get a reference to an embedded view from the custom layout and then manipulate it. |
|||
val tableView = view.findViewById(R.id.simple_table) as ViewGroup |
|||
populateTableRows(position, tableView) |
|||
|
|||
return view |
|||
} |
|||
|
|||
/** Populates all of the rows in the card at the specified position. */ |
|||
private fun populateTableRows(position: Int, tableView: ViewGroup) { |
|||
val startItemIndex = position * ITEMS_PER_CARD |
|||
val endItemIndex = Math.min(startItemIndex + ITEMS_PER_CARD, mItems.size) |
|||
|
|||
for (i in 0 until ITEMS_PER_CARD) { |
|||
val itemIndex = startItemIndex + i |
|||
val rowView = tableView.getChildAt(i) as ViewGroup |
|||
|
|||
// The layout contains four fixed rows, so we need to hide the later ones if there are |
|||
// not four items on this card. We need to make sure to update the visibility in both |
|||
// cases though if the card has been recycled. |
|||
if (itemIndex < endItemIndex) { |
|||
val item = mItems[itemIndex] |
|||
populateTableRow(item, rowView) |
|||
rowView.visibility = View.VISIBLE |
|||
} else { |
|||
rowView.visibility = View.INVISIBLE |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** Populates a row in the table with the specified item data. */ |
|||
private fun populateTableRow(item: SimpleTableItem, rowView: ViewGroup) { |
|||
val imageView = rowView.getChildAt(IMAGE_VIEW_INDEX) as ImageView |
|||
val primaryTextView = rowView.getChildAt(PRIMARY_TEXT_VIEW_INDEX) as TextView |
|||
val secondaryTextView = rowView.getChildAt(SECONDARY_TEXT_VIEW_INDEX) as TextView |
|||
|
|||
imageView.setImageResource(item.iconResId) |
|||
primaryTextView.text = item.primaryText |
|||
secondaryTextView.text = item.secondaryText |
|||
} |
|||
|
|||
companion object { |
|||
|
|||
/** The maximum number of items that fit on a card. */ |
|||
private const val ITEMS_PER_CARD = 4 |
|||
|
|||
/** Index of the [ImageView] containing the icon in a table row. */ |
|||
private const val IMAGE_VIEW_INDEX = 0 |
|||
|
|||
/** Index of the [TextView] containing the primary text in a table row. */ |
|||
private const val PRIMARY_TEXT_VIEW_INDEX = 1 |
|||
|
|||
/** Index of the [TextView] containing the secondary text in a table row. */ |
|||
private const val SECONDARY_TEXT_VIEW_INDEX = 2 |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.card |
|||
|
|||
/** |
|||
* Simple data object used to represent items in a table, which are converted into views by |
|||
* [EmbeddedCardLayoutAdapter]. |
|||
*/ |
|||
data class SimpleTableItem |
|||
/** |
|||
* Initializes a new `SimpleTableItem` with the specified icon, primary text, and |
|||
* secondary text. |
|||
*/ |
|||
( |
|||
/** The image resource ID associated with the table item. */ |
|||
val iconResId: Int, |
|||
/** The primary text associated with the table item. */ |
|||
val primaryText: CharSequence, |
|||
/** The secondary text associated with the table item. */ |
|||
val secondaryText: CharSequence) |
@ -0,0 +1,159 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.opengl |
|||
|
|||
import android.opengl.GLES20 |
|||
|
|||
import java.nio.ByteBuffer |
|||
import java.nio.ByteOrder |
|||
import java.nio.FloatBuffer |
|||
|
|||
/** |
|||
* Renders a 3D Cube using OpenGL ES 2.0. |
|||
* |
|||
* For more information on how to use OpenGL ES 2.0 on Android, see the |
|||
* [ |
|||
* Displaying Graphics with OpenGL ES](//developer.android.com/training/graphics/opengl/index.html) developer guide. |
|||
*/ |
|||
class Cube { |
|||
|
|||
/** Vertex size in bytes. */ |
|||
private val VERTEX_STRIDE = COORDS_PER_VERTEX * 4 |
|||
|
|||
/** Color size in bytes. */ |
|||
private val COLOR_STRIDE = VALUES_PER_COLOR * 4 |
|||
|
|||
|
|||
private val mVertexBuffer: FloatBuffer |
|||
private val mColorBuffer: FloatBuffer |
|||
private val mIndexBuffer: ByteBuffer |
|||
private val mProgram: Int |
|||
private val mPositionHandle: Int |
|||
private val mColorHandle: Int |
|||
private val mMVPMatrixHandle: Int |
|||
|
|||
init { |
|||
var byteBuffer = ByteBuffer.allocateDirect(VERTICES.size * 4) |
|||
|
|||
byteBuffer.order(ByteOrder.nativeOrder()) |
|||
mVertexBuffer = byteBuffer.asFloatBuffer() |
|||
mVertexBuffer.put(VERTICES) |
|||
mVertexBuffer.position(0) |
|||
|
|||
byteBuffer = ByteBuffer.allocateDirect(COLORS.size * 4) |
|||
byteBuffer.order(ByteOrder.nativeOrder()) |
|||
mColorBuffer = byteBuffer.asFloatBuffer() |
|||
mColorBuffer.put(COLORS) |
|||
mColorBuffer.position(0) |
|||
|
|||
mIndexBuffer = ByteBuffer.allocateDirect(INDICES.size) |
|||
mIndexBuffer.put(INDICES) |
|||
mIndexBuffer.position(0) |
|||
|
|||
mProgram = GLES20.glCreateProgram() |
|||
GLES20.glAttachShader(mProgram, loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE)) |
|||
GLES20.glAttachShader( |
|||
mProgram, loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE)) |
|||
GLES20.glLinkProgram(mProgram) |
|||
|
|||
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition") |
|||
mColorHandle = GLES20.glGetAttribLocation(mProgram, "vColor") |
|||
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix") |
|||
} |
|||
|
|||
/** |
|||
* Encapsulates the OpenGL ES instructions for drawing this shape. |
|||
* |
|||
* @param mvpMatrix The Model View Project matrix in which to draw this shape |
|||
*/ |
|||
fun draw(mvpMatrix: FloatArray) { |
|||
// Add program to OpenGL environment. |
|||
GLES20.glUseProgram(mProgram) |
|||
|
|||
// Prepare the cube coordinate data. |
|||
GLES20.glEnableVertexAttribArray(mPositionHandle) |
|||
GLES20.glVertexAttribPointer( |
|||
mPositionHandle, 3, GLES20.GL_FLOAT, false, VERTEX_STRIDE, mVertexBuffer) |
|||
|
|||
// Prepare the cube color data. |
|||
GLES20.glEnableVertexAttribArray(mColorHandle) |
|||
GLES20.glVertexAttribPointer( |
|||
mColorHandle, 4, GLES20.GL_FLOAT, false, COLOR_STRIDE, mColorBuffer) |
|||
|
|||
// Apply the projection and view transformation. |
|||
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0) |
|||
|
|||
// Draw the cube. |
|||
GLES20.glDrawElements( |
|||
GLES20.GL_TRIANGLES, INDICES.size, GLES20.GL_UNSIGNED_BYTE, mIndexBuffer) |
|||
|
|||
// Disable vertex arrays. |
|||
GLES20.glDisableVertexAttribArray(mPositionHandle) |
|||
GLES20.glDisableVertexAttribArray(mColorHandle) |
|||
} |
|||
|
|||
companion object { |
|||
|
|||
/** Cube vertices */ |
|||
private val VERTICES = floatArrayOf(-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f) |
|||
|
|||
/** Vertex colors. */ |
|||
private val COLORS = floatArrayOf(0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f) |
|||
|
|||
|
|||
/** Order to draw vertices as triangles. */ |
|||
private val INDICES = byteArrayOf(0, 1, 3, 3, 1, 2, // Front face. |
|||
0, 1, 4, 4, 5, 1, // Bottom face. |
|||
1, 2, 5, 5, 6, 2, // Right face. |
|||
2, 3, 6, 6, 7, 3, // Top face. |
|||
3, 7, 4, 4, 3, 0, // Left face. |
|||
4, 5, 7, 7, 6, 5)// Rear face. |
|||
|
|||
/** Number of coordinates per vertex in [VERTICES]. */ |
|||
private const val COORDS_PER_VERTEX = 3 |
|||
|
|||
/** Number of values per colors in [COLORS]. */ |
|||
private const val VALUES_PER_COLOR = 4 |
|||
|
|||
/** Shader code for the vertex. */ |
|||
private const val VERTEX_SHADER_CODE = "uniform mat4 uMVPMatrix;" + |
|||
"attribute vec4 vPosition;" + |
|||
"attribute vec4 vColor;" + |
|||
"varying vec4 _vColor;" + |
|||
"void main() {" + |
|||
" _vColor = vColor;" + |
|||
" gl_Position = uMVPMatrix * vPosition;" + |
|||
"}" |
|||
|
|||
/** Shader code for the fragment. */ |
|||
private const val FRAGMENT_SHADER_CODE = "precision mediump float;" + |
|||
"varying vec4 _vColor;" + |
|||
"void main() {" + |
|||
" gl_FragColor = _vColor;" + |
|||
"}" |
|||
|
|||
/** Loads the provided shader in the program. */ |
|||
private fun loadShader(type: Int, shaderCode: String): Int { |
|||
val shader = GLES20.glCreateShader(type) |
|||
|
|||
GLES20.glShaderSource(shader, shaderCode) |
|||
GLES20.glCompileShader(shader) |
|||
|
|||
return shader |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,100 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.opengl |
|||
|
|||
import com.google.android.glass.timeline.GlRenderer |
|||
|
|||
import android.opengl.GLES20 |
|||
import android.opengl.Matrix |
|||
import android.os.SystemClock |
|||
|
|||
import java.util.concurrent.TimeUnit |
|||
import javax.microedition.khronos.egl.EGLConfig |
|||
|
|||
/** |
|||
* Renders a 3D OpenGL Cube on a [LiveCard]. |
|||
*/ |
|||
class CubeRenderer : GlRenderer { |
|||
|
|||
private val mMVPMatrix: FloatArray = FloatArray(16) |
|||
private val mProjectionMatrix: FloatArray = FloatArray(16) |
|||
private val mViewMatrix: FloatArray = FloatArray(16) |
|||
private val mRotationMatrix: FloatArray = FloatArray(16) |
|||
private val mFinalMVPMatrix: FloatArray = FloatArray(16) |
|||
|
|||
private lateinit var mCube: Cube |
|||
private var mCubeRotation: Float = 0.toFloat() |
|||
private var mLastUpdateMillis: Long = 0 |
|||
|
|||
init { |
|||
// Set the fixed camera position (View matrix). |
|||
Matrix.setLookAtM(mViewMatrix, 0, 0.0f, 0.0f, -4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f) |
|||
} |
|||
|
|||
override fun onSurfaceCreated(config: EGLConfig) { |
|||
// Set the background frame color |
|||
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) |
|||
GLES20.glClearDepthf(1.0f) |
|||
GLES20.glEnable(GLES20.GL_DEPTH_TEST) |
|||
GLES20.glDepthFunc(GLES20.GL_LEQUAL) |
|||
mCube = Cube() |
|||
} |
|||
|
|||
override fun onSurfaceChanged(width: Int, height: Int) { |
|||
val ratio = width.toFloat() / height |
|||
|
|||
GLES20.glViewport(0, 0, width, height) |
|||
// This projection matrix is applied to object coordinates in the onDrawFrame() method. |
|||
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1.0f, 1.0f, 3.0f, 7.0f) |
|||
// modelView = projection x view |
|||
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0) |
|||
} |
|||
|
|||
override fun onDrawFrame() { |
|||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT) |
|||
|
|||
// Apply the rotation. |
|||
Matrix.setRotateM(mRotationMatrix, 0, mCubeRotation, 1.0f, 1.0f, 1.0f) |
|||
// Combine the rotation matrix with the projection and camera view |
|||
Matrix.multiplyMM(mFinalMVPMatrix, 0, mMVPMatrix, 0, mRotationMatrix, 0) |
|||
|
|||
// Draw cube. |
|||
mCube.draw(mFinalMVPMatrix) |
|||
updateCubeRotation() |
|||
} |
|||
|
|||
/** Updates the cube rotation. */ |
|||
private fun updateCubeRotation() { |
|||
if (mLastUpdateMillis != 0L) { |
|||
val factor = (SystemClock.elapsedRealtime() - mLastUpdateMillis) / FRAME_TIME_MILLIS |
|||
mCubeRotation += CUBE_ROTATION_INCREMENT * factor |
|||
} |
|||
mLastUpdateMillis = SystemClock.elapsedRealtime() |
|||
} |
|||
|
|||
companion object { |
|||
|
|||
/** Rotation increment per frame. */ |
|||
private const val CUBE_ROTATION_INCREMENT = 0.6f |
|||
|
|||
/** The refresh rate, in frames per second. */ |
|||
private const val REFRESH_RATE_FPS = 60 |
|||
|
|||
/** The duration, in milliseconds, of one frame. */ |
|||
private val FRAME_TIME_MILLIS = (TimeUnit.SECONDS.toMillis(1) / REFRESH_RATE_FPS).toFloat() |
|||
} |
|||
} |
@ -0,0 +1,67 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.opengl |
|||
|
|||
import com.google.android.glass.sample.apidemo.R |
|||
|
|||
import android.app.Activity |
|||
import android.content.Intent |
|||
import android.os.Bundle |
|||
import android.os.Handler |
|||
import android.view.Menu |
|||
import android.view.MenuInflater |
|||
import android.view.MenuItem |
|||
|
|||
import java.lang.Runnable |
|||
|
|||
/** |
|||
* Activity showing an options menu to stop the [OpenGlService]. |
|||
*/ |
|||
class MenuActivity : Activity() { |
|||
|
|||
private val mHandler = Handler() |
|||
|
|||
override fun onAttachedToWindow() { |
|||
super.onAttachedToWindow() |
|||
openOptionsMenu() |
|||
} |
|||
|
|||
override fun onCreateOptionsMenu(menu: Menu): Boolean { |
|||
val inflater = menuInflater |
|||
inflater.inflate(R.menu.opengl_livecard, menu) |
|||
return true |
|||
} |
|||
|
|||
override fun onOptionsItemSelected(item: MenuItem): Boolean { |
|||
// Handle item selection. |
|||
return when (item.itemId) { |
|||
R.id.stop -> { |
|||
// Stop the service at the end of the message queue for proper options menu |
|||
// animation. This is only needed when starting a new Activity or stopping a Service |
|||
// that published a LiveCard. |
|||
mHandler.post { stopService(Intent(this@MenuActivity, OpenGlService::class.java)) } |
|||
true |
|||
} |
|||
else -> super.onOptionsItemSelected(item) |
|||
} |
|||
} |
|||
|
|||
override fun onOptionsMenuClosed(menu: Menu) { |
|||
// Nothing else to do, closing the Activity. |
|||
finish() |
|||
} |
|||
} |
@ -0,0 +1,64 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||
|
|||
package com.google.android.glass.sample.apidemo.opengl |
|||
|
|||
import com.google.android.glass.timeline.LiveCard |
|||
import com.google.android.glass.timeline.LiveCard.PublishMode |
|||
|
|||
import android.app.PendingIntent |
|||
import android.app.Service |
|||
import android.content.Intent |
|||
import android.os.IBinder |
|||
|
|||
/** |
|||
* Creates a [LiveCard] rendering a rotating 3D cube with OpenGL. |
|||
*/ |
|||
class OpenGlService : Service() { |
|||
|
|||
private var mLiveCard: LiveCard? = null |
|||
|
|||
override fun onBind(intent: Intent): IBinder? { |
|||
return null |
|||
} |
|||
|
|||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { |
|||
if (mLiveCard == null) { |
|||
mLiveCard = LiveCard(this, LIVE_CARD_TAG) |
|||
mLiveCard!!.setRenderer(CubeRenderer()) |
|||
mLiveCard!!.setAction( |
|||
PendingIntent.getActivity(this, 0, Intent(this, MenuActivity::class.java), 0)) |
|||
mLiveCard!!.attach(this) |
|||
mLiveCard!!.publish(PublishMode.REVEAL) |
|||
} else { |
|||
mLiveCard!!.navigate() |
|||
} |
|||
|
|||
return START_STICKY |
|||
} |
|||
|
|||
override fun onDestroy() { |
|||
if (mLiveCard != null && mLiveCard!!.isPublished) { |
|||
mLiveCard!!.unpublish() |
|||
mLiveCard = null |
|||
} |
|||
super.onDestroy() |
|||
} |
|||
|
|||
companion object { |
|||
private const val LIVE_CARD_TAG = "opengl" |
|||
} |
|||
} |
@ -0,0 +1,176 @@ |
|||
/* |
|||
* Copyright (C) 2014 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. |
|||
*/ |
|||