Adding new samples to browseable section of DAC
Change-Id: I58e10e787f5df668331fc04e97a6c2efcd75f76f
@@ -1,32 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2013 The Android Open Source Project
|
~ Copyright 2013 The Android Open Source Project
|
||||||
|
~
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
~ you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
Unless required by applicable law or agreed to in writing, software
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<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>
|
</resources>
|
||||||
|
|||||||
73
samples/browseable/AdvancedImmersiveMode/res/layout-w720dp/activity_main.xml
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
<!--
|
||||||
|
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:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/sample_main_layout">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sample_output"
|
||||||
|
android:layout_width="0px"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
style="@style/Widget.SampleMessageTile"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/Widget.SampleMessage"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="@dimen/margin_medium"
|
||||||
|
android:paddingRight="@dimen/margin_medium"
|
||||||
|
android:paddingTop="@dimen/margin_large"
|
||||||
|
android:paddingBottom="@dimen/margin_large"
|
||||||
|
android:text="@string/intro_message" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@android:color/darker_gray" />
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:name="com.example.android.common.logger.LogFragment"
|
||||||
|
android:id="@+id/log_fragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0px"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/darker_gray" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/sample_content_fragment"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:layout_width="0px"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/flag_enable_lowprof"
|
||||||
|
android:text="Enable Low Profile Mode" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/flag_hide_navbar"
|
||||||
|
android:text="Hide Navigation bar" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/flag_hide_statbar"
|
||||||
|
android:text="Hide Status Bar" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/flag_enable_immersive"
|
||||||
|
android:text="Enable Immersive Mode" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/flag_enable_immersive_sticky"
|
||||||
|
android:text="Enable Immersive Mode (Sticky)" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Do things!"
|
||||||
|
android:id="@+id/btn_changeFlags" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_marginTop="@dimen/margin_large"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Common flag presets"/>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="horizontal" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Immersive Mode"
|
||||||
|
android:id="@+id/btn_immersive" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Leanback Mode"
|
||||||
|
android:id="@+id/btn_leanback" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
0
samples/browseable/AdvancedImmersiveMode/res/values/strings.xml
Normal file → Executable file
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Copyright 2013 The Android Open Source Project
|
Copyright (C) 2013 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -13,20 +13,8 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<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>
|
</resources>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!--
|
||||||
|
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:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:id="@+id/sample_main_layout">
|
||||||
|
<TextView android:id="@+id/sample_output"
|
||||||
|
style="@style/Widget.SampleMessage"
|
||||||
|
android:background="@android:color/white"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/intro_message"
|
||||||
|
android:layout_margin="16dp" />
|
||||||
|
<fragment
|
||||||
|
android:name="com.example.android.common.logger.LogFragment"
|
||||||
|
android:id="@+id/log_fragment"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
@@ -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:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:id="@+id/sample_main_layout">
|
||||||
|
<TextView android:id="@+id/sample_output"
|
||||||
|
style="@style/Widget.SampleMessage"
|
||||||
|
android:background="@android:color/white"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/intro_message"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:layout_margin="16dp"/>
|
||||||
|
<fragment
|
||||||
|
android:name="com.example.android.common.logger.LogFragment"
|
||||||
|
android:id="@+id/log_fragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="@string/intro_message" />
|
android:text="@string/intro_message"
|
||||||
|
android:padding="16dp" />
|
||||||
<View
|
<View
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
|
|||||||
@@ -26,8 +26,11 @@
|
|||||||
<style name="Widget" />
|
<style name="Widget" />
|
||||||
|
|
||||||
<style name="Widget.SampleMessage">
|
<style name="Widget.SampleMessage">
|
||||||
|
<item name="android:padding">@dimen/margin_medium</item>
|
||||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||||
|
<item name="android:layout_margin">16dp</item>
|
||||||
|
<item name="android:shadowDy">-6.5</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.SampleMessageTile">
|
<style name="Widget.SampleMessageTile">
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.example.android.basicandroidkeystore;
|
package com.example.android.basicandroidkeystore;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -72,6 +73,8 @@ public class MainActivity extends SampleActivityBase {
|
|||||||
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
|
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
|
||||||
.findFragmentById(R.id.log_fragment);
|
.findFragmentById(R.id.log_fragment);
|
||||||
msgFilter.setNext(logFragment.getLogView());
|
msgFilter.setNext(logFragment.getLogView());
|
||||||
|
logFragment.getLogView().setTextAppearance(this, R.style.Log);
|
||||||
|
logFragment.getLogView().setBackgroundColor(Color.WHITE);
|
||||||
|
|
||||||
Log.i(TAG, "Ready");
|
Log.i(TAG, "Ready");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright 2013 The Android Open Source Project
|
Copyright 2013 The Android Open Source Project
|
||||||
|
|
||||||
@@ -15,28 +16,12 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Activity themes -->
|
|
||||||
|
|
||||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
|
||||||
|
|
||||||
<style name="Theme.Sample" parent="Theme.Base" />
|
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.Sample" />
|
|
||||||
<!-- Widget styling -->
|
<!-- Widget styling -->
|
||||||
|
|
||||||
<style name="Widget" />
|
<style name="Widget.SampleOutput">
|
||||||
|
<item name="android:padding">@dimen/margin_medium</item>
|
||||||
<style name="Widget.SampleMessage">
|
|
||||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||||
</style>
|
</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>
|
</resources>
|
||||||
|
|||||||
@@ -1,42 +1,22 @@
|
|||||||
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Copyright 2013 The Android Open Source Project
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
-->
|
||||||
you may not use this file except in compliance with the License.
|
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||||
You may obtain a copy of the License at
|
<!--
|
||||||
|
Theme customizations available in newer API levels can go in
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
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.Holo.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>
|
||||||
|
|
||||||
<style name="Widget.SampleMessageTile">
|
|
||||||
<item name="android:background">@drawable/tile</item>
|
<style name="DisplayLargeText">
|
||||||
<item name="android:shadowColor">#7F000000</item>
|
<item name="android:textSize">30sp</item>
|
||||||
<item name="android:shadowDy">-3.5</item>
|
<item name="android:textStyle">bold</item>
|
||||||
<item name="android:shadowRadius">2</item>
|
<item name="android:textColor">#FFFFFF</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -13,30 +13,18 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Activity themes -->
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
<style name="Theme.Sample" parent="Theme.Base" />
|
<style name="AppBaseTheme" parent="android:Theme.Light.NoTitleBar">
|
||||||
|
<!--
|
||||||
<style name="AppTheme" parent="Theme.Sample" />
|
Theme customizations available in newer API levels can go in
|
||||||
<!-- Widget styling -->
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
<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>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under thegi License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
@@ -16,27 +16,17 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Activity themes -->
|
|
||||||
|
|
||||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
|
||||||
|
|
||||||
<style name="Theme.Sample" parent="Theme.Base" />
|
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.Sample" />
|
|
||||||
<!-- Widget styling -->
|
<!-- Widget styling -->
|
||||||
|
|
||||||
<style name="Widget" />
|
<style name="Widget.SampleOutput">
|
||||||
|
<item name="android:padding">@dimen/margin_medium</item>
|
||||||
<style name="Widget.SampleMessage">
|
|
||||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.SampleMessageTile">
|
<style name="Log" parent="Widget.SampleOutput">
|
||||||
<item name="android:background">@drawable/tile</item>
|
<item name="android:typeface">monospace</item>
|
||||||
<item name="android:shadowColor">#7F000000</item>
|
|
||||||
<item name="android:shadowDy">-3.5</item>
|
|
||||||
<item name="android:shadowRadius">2</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
45
samples/browseable/BasicRenderScript/AndroidManifest.xml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><!--
|
||||||
|
Copyright 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.android.basicrenderscript"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="8"
|
||||||
|
android:targetSdkVersion="19" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/FullscreenTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
</manifest>
|
||||||
13
samples/browseable/BasicRenderScript/_index.jd
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
page.tags="BasicRenderScript"
|
||||||
|
sample.group=RenderScript
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
|
BasicRenderScript sample demonstrates basic steps how to use renderScript.
|
||||||
|
In the sample, it performs graphical filter operation on a image with renderScript.
|
||||||
|
|
||||||
|
</p>
|
||||||
BIN
samples/browseable/BasicRenderScript/res/drawable-hdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 196 B After Width: | Height: | Size: 196 B |
BIN
samples/browseable/BasicRenderScript/res/drawable-mdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
samples/browseable/BasicRenderScript/res/drawable-nodpi/data.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
samples/browseable/BasicRenderScript/res/drawable-xhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
samples/browseable/BasicRenderScript/res/drawable-xxhdpi/ic_launcher.png
Executable file
|
After Width: | Height: | Size: 11 KiB |
36
samples/browseable/BasicRenderScript/res/layout/activity_main.xml
Executable file
@@ -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>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<FrameLayout 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:background="#0099cc"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/data" />
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/seekBar1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 11+. This theme completely replaces
|
||||||
|
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||||
|
<!-- API 11 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FullscreenTheme" parent="android:Theme.Holo">
|
||||||
|
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
|
||||||
|
<item name="android:windowActionBarOverlay">true</item>
|
||||||
|
<item name="android:windowBackground">@null</item>
|
||||||
|
<item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
|
||||||
|
<item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FullscreenActionBarStyle" parent="android:Widget.Holo.ActionBar">
|
||||||
|
<item name="android:background">@color/black_overlay</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 14+. This theme completely replaces
|
||||||
|
AppBaseTheme from BOTH res/values/styles.xml and
|
||||||
|
res/values-v11/styles.xml on API 14+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||||
|
<!-- API 14 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
14
samples/browseable/BasicRenderScript/res/values/attrs.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Declare custom theme attributes that allow changing which styles are
|
||||||
|
used for button bars depending on the API level.
|
||||||
|
?android:attr/buttonBarStyle is new as of API 11 so this is
|
||||||
|
necessary to support previous API levels.
|
||||||
|
-->
|
||||||
|
<declare-styleable name="ButtonBarContainerTheme">
|
||||||
|
<attr name="buttonBarStyle" format="reference" />
|
||||||
|
<attr name="buttonBarButtonStyle" format="reference" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?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">BasicRenderScript</string>
|
||||||
|
<string name="intro_message">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
|
||||||
|
BasicRenderScript sample demonstrates basic steps how to use renderScript.
|
||||||
|
In the sample, it performs graphical filter operation on a image with renderScript.
|
||||||
|
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<color name="black_overlay">#66000000</color>
|
||||||
|
|
||||||
|
</resources>
|
||||||
22
samples/browseable/BasicRenderScript/res/values/styles.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
|
||||||
|
<style name="FullscreenTheme" parent="android:Theme.NoTitleBar">
|
||||||
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
|
<item name="android:windowBackground">@null</item>
|
||||||
|
<item name="buttonBarStyle">@style/ButtonBar</item>
|
||||||
|
<item name="buttonBarButtonStyle">@style/ButtonBarButton</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ButtonBar">
|
||||||
|
<item name="android:paddingLeft">2dp</item>
|
||||||
|
<item name="android:paddingTop">5dp</item>
|
||||||
|
<item name="android:paddingRight">2dp</item>
|
||||||
|
<item name="android:paddingBottom">0dp</item>
|
||||||
|
<item name="android:background">@android:drawable/bottom_bar</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ButtonBarButton" />
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* 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.example.android.basicrenderscript;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||||
|
import android.support.v8.renderscript.*;
|
||||||
|
|
||||||
|
public class MainActivity extends Activity {
|
||||||
|
/* Number of bitmaps that is used for renderScript thread and UI thread synchronization.
|
||||||
|
Ideally, this can be reduced to 2, however in some devices, 2 buffers still showing tierings on UI.
|
||||||
|
Investigating a root cause.
|
||||||
|
*/
|
||||||
|
private final int NUM_BITMAPS = 3;
|
||||||
|
private int mCurrentBitmap = 0;
|
||||||
|
private Bitmap mBitmapIn;
|
||||||
|
private Bitmap[] mBitmapsOut;
|
||||||
|
private ImageView mImageView;
|
||||||
|
|
||||||
|
private RenderScript mRS;
|
||||||
|
private Allocation mInAllocation;
|
||||||
|
private Allocation[] mOutAllocations;
|
||||||
|
private ScriptC_saturation mScript;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.main_layout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize UI
|
||||||
|
*/
|
||||||
|
mBitmapIn = loadBitmap(R.drawable.data);
|
||||||
|
mBitmapsOut = new Bitmap[NUM_BITMAPS];
|
||||||
|
for (int i = 0; i < NUM_BITMAPS; ++i) {
|
||||||
|
mBitmapsOut[i] = Bitmap.createBitmap(mBitmapIn.getWidth(),
|
||||||
|
mBitmapIn.getHeight(), mBitmapIn.getConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
mImageView = (ImageView) findViewById(R.id.imageView);
|
||||||
|
mImageView.setImageBitmap(mBitmapsOut[mCurrentBitmap]);
|
||||||
|
mCurrentBitmap += (mCurrentBitmap + 1) % NUM_BITMAPS;
|
||||||
|
|
||||||
|
SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar1);
|
||||||
|
seekbar.setProgress(50);
|
||||||
|
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||||
|
boolean fromUser) {
|
||||||
|
float max = 2.0f;
|
||||||
|
float min = 0.0f;
|
||||||
|
float f = (float) ((max - min) * (progress / 100.0) + min);
|
||||||
|
updateImage(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create renderScript
|
||||||
|
*/
|
||||||
|
createScript();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invoke renderScript kernel and update imageView
|
||||||
|
*/
|
||||||
|
updateImage(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize RenderScript
|
||||||
|
* In the sample, it creates RenderScript kernel that performs saturation manipulation.
|
||||||
|
*/
|
||||||
|
private void createScript() {
|
||||||
|
//Initialize RS
|
||||||
|
mRS = RenderScript.create(this);
|
||||||
|
|
||||||
|
//Allocate buffers
|
||||||
|
mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
|
||||||
|
mOutAllocations = new Allocation[NUM_BITMAPS];
|
||||||
|
for (int i = 0; i < NUM_BITMAPS; ++i) {
|
||||||
|
mOutAllocations[i] = Allocation.createFromBitmap(mRS, mBitmapsOut[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load script
|
||||||
|
mScript = new ScriptC_saturation(mRS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the AsyncTask, it invokes RenderScript intrinsics to do a filtering.
|
||||||
|
* After the filtering is done, an operation blocks at Allication.copyTo() in AsyncTask thread.
|
||||||
|
* Once all operation is finished at onPostExecute() in UI thread, it can invalidate and update ImageView UI.
|
||||||
|
*/
|
||||||
|
private class RenderScriptTask extends AsyncTask<Float, Integer, Integer> {
|
||||||
|
Boolean issued = false;
|
||||||
|
|
||||||
|
protected Integer doInBackground(Float... values) {
|
||||||
|
int index = -1;
|
||||||
|
if (isCancelled() == false) {
|
||||||
|
issued = true;
|
||||||
|
index = mCurrentBitmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set global variable in RS
|
||||||
|
*/
|
||||||
|
mScript.set_saturationValue(values[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invoke saturation filter kernel
|
||||||
|
*/
|
||||||
|
mScript.forEach_saturation(mInAllocation, mOutAllocations[index]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy to bitmap and invalidate image view
|
||||||
|
*/
|
||||||
|
mOutAllocations[index].copyTo(mBitmapsOut[index]);
|
||||||
|
mCurrentBitmap = (mCurrentBitmap + 1) % NUM_BITMAPS;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateView(Integer result) {
|
||||||
|
if (result != -1) {
|
||||||
|
// Request UI update
|
||||||
|
mImageView.setImageBitmap(mBitmapsOut[result]);
|
||||||
|
mImageView.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Integer result) {
|
||||||
|
updateView(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onCancelled(Integer result) {
|
||||||
|
if (issued) {
|
||||||
|
updateView(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderScriptTask currentTask = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Invoke AsynchTask and cancel previous task.
|
||||||
|
When AsyncTasks are piled up (typically in slow device with heavy kernel),
|
||||||
|
Only the latest (and already started) task invokes RenderScript operation.
|
||||||
|
*/
|
||||||
|
private void updateImage(final float f) {
|
||||||
|
if (currentTask != null)
|
||||||
|
currentTask.cancel(false);
|
||||||
|
currentTask = new RenderScriptTask();
|
||||||
|
currentTask.execute(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper to load Bitmap from resource
|
||||||
|
*/
|
||||||
|
private Bitmap loadBitmap(int resource) {
|
||||||
|
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||||
|
return BitmapFactory.decodeResource(getResources(), resource, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* 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.example.android.common.media;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camera related utilities.
|
||||||
|
*/
|
||||||
|
public class CameraHelper {
|
||||||
|
|
||||||
|
public static final int MEDIA_TYPE_IMAGE = 1;
|
||||||
|
public static final int MEDIA_TYPE_VIDEO = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over supported camera preview sizes to see which one best fits the
|
||||||
|
* dimensions of the given view while maintaining the aspect ratio. If none can,
|
||||||
|
* be lenient with the aspect ratio.
|
||||||
|
*
|
||||||
|
* @param sizes Supported camera preview sizes.
|
||||||
|
* @param w The width of the view.
|
||||||
|
* @param h The height of the view.
|
||||||
|
* @return Best match camera preview size to fit in the view.
|
||||||
|
*/
|
||||||
|
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
|
||||||
|
// Use a very small tolerance because we want an exact match.
|
||||||
|
final double ASPECT_TOLERANCE = 0.1;
|
||||||
|
double targetRatio = (double) w / h;
|
||||||
|
if (sizes == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Camera.Size optimalSize = null;
|
||||||
|
|
||||||
|
// Start with max value and refine as we iterate over available preview sizes. This is the
|
||||||
|
// minimum difference between view and camera height.
|
||||||
|
double minDiff = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
// Target view height
|
||||||
|
int targetHeight = h;
|
||||||
|
|
||||||
|
// Try to find a preview size that matches aspect ratio and the target view size.
|
||||||
|
// Iterate over all available sizes and pick the largest size that can fit in the view and
|
||||||
|
// still maintain the aspect ratio.
|
||||||
|
for (Camera.Size size : sizes) {
|
||||||
|
double ratio = (double) size.width / size.height;
|
||||||
|
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
|
||||||
|
continue;
|
||||||
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||||
|
optimalSize = size;
|
||||||
|
minDiff = Math.abs(size.height - targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot find preview size that matches the aspect ratio, ignore the requirement
|
||||||
|
if (optimalSize == null) {
|
||||||
|
minDiff = Double.MAX_VALUE;
|
||||||
|
for (Camera.Size size : sizes) {
|
||||||
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||||
|
optimalSize = size;
|
||||||
|
minDiff = Math.abs(size.height - targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optimalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default camera on the device. Return null if there is no camera on the device.
|
||||||
|
*/
|
||||||
|
public static Camera getDefaultCameraInstance() {
|
||||||
|
return Camera.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default rear/back facing camera on the device. Returns null if camera is not
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
public static Camera getDefaultBackFacingCameraInstance() {
|
||||||
|
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default front facing camera on the device. Returns null if camera is not
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
public static Camera getDefaultFrontFacingCameraInstance() {
|
||||||
|
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT
|
||||||
|
* or Camera.CameraInfo.CAMERA_FACING_BACK.
|
||||||
|
* @return the default camera on the device. Returns null if camera is not available.
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||||
|
private static Camera getDefaultCamera(int position) {
|
||||||
|
// Find the total number of cameras available
|
||||||
|
int mNumberOfCameras = Camera.getNumberOfCameras();
|
||||||
|
|
||||||
|
// Find the ID of the back-facing ("default") camera
|
||||||
|
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
||||||
|
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||||
|
Camera.getCameraInfo(i, cameraInfo);
|
||||||
|
if (cameraInfo.facing == position) {
|
||||||
|
return Camera.open(i);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory
|
||||||
|
* is persistent and available to other applications like gallery.
|
||||||
|
*
|
||||||
|
* @param type Media type. Can be video or image.
|
||||||
|
* @return A file object pointing to the newly created file.
|
||||||
|
*/
|
||||||
|
public static File getOutputMediaFile(int type){
|
||||||
|
// To be safe, you should check that the SDCard is mounted
|
||||||
|
// using Environment.getExternalStorageState() before doing this.
|
||||||
|
if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
|
||||||
|
Environment.DIRECTORY_PICTURES), "CameraSample");
|
||||||
|
// This location works best if you want the created images to be shared
|
||||||
|
// between applications and persist after your app has been uninstalled.
|
||||||
|
|
||||||
|
// Create the storage directory if it does not exist
|
||||||
|
if (! mediaStorageDir.exists()){
|
||||||
|
if (! mediaStorageDir.mkdirs()) {
|
||||||
|
Log.d("CameraSample", "failed to create directory");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a media file name
|
||||||
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||||
|
File mediaFile;
|
||||||
|
if (type == MEDIA_TYPE_IMAGE){
|
||||||
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||||
|
"IMG_"+ timeStamp + ".jpg");
|
||||||
|
} else if(type == MEDIA_TYPE_VIDEO) {
|
||||||
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||||
|
"VID_"+ timeStamp + ".mp4");
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mediaFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,386 @@
|
|||||||
|
/*
|
||||||
|
* 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.example.android.common.media;
|
||||||
|
|
||||||
|
import android.media.*;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplifies the MediaCodec interface by wrapping around the buffer processing operations.
|
||||||
|
*/
|
||||||
|
public class MediaCodecWrapper {
|
||||||
|
|
||||||
|
// Handler to use for {@code OutputSampleListener} and {code OutputFormatChangedListener}
|
||||||
|
// callbacks
|
||||||
|
private Handler mHandler;
|
||||||
|
|
||||||
|
|
||||||
|
// Callback when media output format changes.
|
||||||
|
public interface OutputFormatChangedListener {
|
||||||
|
void outputFormatChanged(MediaCodecWrapper sender, MediaFormat newFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputFormatChangedListener mOutputFormatChangedListener = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for decodes frames. Observers can register a listener for optional stream
|
||||||
|
* of decoded data
|
||||||
|
*/
|
||||||
|
public interface OutputSampleListener {
|
||||||
|
void outputSample(MediaCodecWrapper sender, MediaCodec.BufferInfo info, ByteBuffer buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MediaCodec} that is managed by this class.
|
||||||
|
*/
|
||||||
|
private MediaCodec mDecoder;
|
||||||
|
|
||||||
|
// References to the internal buffers managed by the codec. The codec
|
||||||
|
// refers to these buffers by index, never by reference so it's up to us
|
||||||
|
// to keep track of which buffer is which.
|
||||||
|
private ByteBuffer[] mInputBuffers;
|
||||||
|
private ByteBuffer[] mOutputBuffers;
|
||||||
|
|
||||||
|
// Indices of the input buffers that are currently available for writing. We'll
|
||||||
|
// consume these in the order they were dequeued from the codec.
|
||||||
|
private Queue<Integer> mAvailableInputBuffers;
|
||||||
|
|
||||||
|
// Indices of the output buffers that currently hold valid data, in the order
|
||||||
|
// they were produced by the codec.
|
||||||
|
private Queue<Integer> mAvailableOutputBuffers;
|
||||||
|
|
||||||
|
// Information about each output buffer, by index. Each entry in this array
|
||||||
|
// is valid if and only if its index is currently contained in mAvailableOutputBuffers.
|
||||||
|
private MediaCodec.BufferInfo[] mOutputBufferInfo;
|
||||||
|
|
||||||
|
// An (optional) stream that will receive decoded data.
|
||||||
|
private OutputSampleListener mOutputSampleListener;
|
||||||
|
|
||||||
|
private MediaCodecWrapper(MediaCodec codec) {
|
||||||
|
mDecoder = codec;
|
||||||
|
codec.start();
|
||||||
|
mInputBuffers = codec.getInputBuffers();
|
||||||
|
mOutputBuffers = codec.getOutputBuffers();
|
||||||
|
mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
|
||||||
|
mAvailableInputBuffers = new ArrayDeque<Integer>(mOutputBuffers.length);
|
||||||
|
mAvailableOutputBuffers = new ArrayDeque<Integer>(mInputBuffers.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases resources and ends the encoding/decoding session.
|
||||||
|
*/
|
||||||
|
public void stopAndRelease() {
|
||||||
|
mDecoder.stop();
|
||||||
|
mDecoder.release();
|
||||||
|
mDecoder = null;
|
||||||
|
mHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for the registered {@link OutputFormatChangedListener}
|
||||||
|
*/
|
||||||
|
public OutputFormatChangedListener getOutputFormatChangedListener() {
|
||||||
|
return mOutputFormatChangedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param outputFormatChangedListener the listener for callback.
|
||||||
|
* @param handler message handler for posting the callback.
|
||||||
|
*/
|
||||||
|
public void setOutputFormatChangedListener(final OutputFormatChangedListener
|
||||||
|
outputFormatChangedListener, Handler handler) {
|
||||||
|
mOutputFormatChangedListener = outputFormatChangedListener;
|
||||||
|
|
||||||
|
// Making sure we don't block ourselves due to a bad implementation of the callback by
|
||||||
|
// using a handler provided by client.
|
||||||
|
Looper looper;
|
||||||
|
mHandler = handler;
|
||||||
|
if (outputFormatChangedListener != null && mHandler == null) {
|
||||||
|
if ((looper = Looper.myLooper()) != null) {
|
||||||
|
mHandler = new Handler();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Looper doesn't exist in the calling thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the {@link MediaCodecWrapper} wrapper object around the video codec.
|
||||||
|
* The codec is created using the encapsulated information in the
|
||||||
|
* {@link MediaFormat} object.
|
||||||
|
*
|
||||||
|
* @param trackFormat The format of the media object to be decoded.
|
||||||
|
* @param surface Surface to render the decoded frames.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static MediaCodecWrapper fromVideoFormat(final MediaFormat trackFormat,
|
||||||
|
Surface surface) {
|
||||||
|
MediaCodecWrapper result = null;
|
||||||
|
MediaCodec videoCodec = null;
|
||||||
|
|
||||||
|
// BEGIN_INCLUDE(create_codec)
|
||||||
|
final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
|
||||||
|
|
||||||
|
// Check to see if this is actually a video mime type. If it is, then create
|
||||||
|
// a codec that can decode this mime type.
|
||||||
|
if (mimeType.contains("video/")) {
|
||||||
|
videoCodec = MediaCodec.createDecoderByType(mimeType);
|
||||||
|
videoCodec.configure(trackFormat, surface, null, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If codec creation was successful, then create a wrapper object around the
|
||||||
|
// newly created codec.
|
||||||
|
if (videoCodec != null) {
|
||||||
|
result = new MediaCodecWrapper(videoCodec);
|
||||||
|
}
|
||||||
|
// END_INCLUDE(create_codec)
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a media sample to the decoder.
|
||||||
|
*
|
||||||
|
* A "sample" here refers to a single atomic access unit in the media stream. The definition
|
||||||
|
* of "access unit" is dependent on the type of encoding used, but it typically refers to
|
||||||
|
* a single frame of video or a few seconds of audio. {@link android.media.MediaExtractor}
|
||||||
|
* extracts data from a stream one sample at a time.
|
||||||
|
*
|
||||||
|
* @param input A ByteBuffer containing the input data for one sample. The buffer must be set
|
||||||
|
* up for reading, with its position set to the beginning of the sample data and its limit
|
||||||
|
* set to the end of the sample data.
|
||||||
|
*
|
||||||
|
* @param presentationTimeUs The time, relative to the beginning of the media stream,
|
||||||
|
* at which this buffer should be rendered.
|
||||||
|
*
|
||||||
|
* @param flags Flags to pass to the decoder. See {@link MediaCodec#queueInputBuffer(int,
|
||||||
|
* int, int, long, int)}
|
||||||
|
*
|
||||||
|
* @throws MediaCodec.CryptoException
|
||||||
|
*/
|
||||||
|
public boolean writeSample(final ByteBuffer input,
|
||||||
|
final MediaCodec.CryptoInfo crypto,
|
||||||
|
final long presentationTimeUs,
|
||||||
|
final int flags) throws MediaCodec.CryptoException, WriteException {
|
||||||
|
boolean result = false;
|
||||||
|
int size = input.remaining();
|
||||||
|
|
||||||
|
// check if we have dequed input buffers available from the codec
|
||||||
|
if (size > 0 && !mAvailableInputBuffers.isEmpty()) {
|
||||||
|
int index = mAvailableInputBuffers.remove();
|
||||||
|
ByteBuffer buffer = mInputBuffers[index];
|
||||||
|
|
||||||
|
// we can't write our sample to a lesser capacity input buffer.
|
||||||
|
if (size > buffer.capacity()) {
|
||||||
|
throw new MediaCodecWrapper.WriteException(String.format(
|
||||||
|
"Insufficient capacity in MediaCodec buffer: "
|
||||||
|
+ "tried to write %d, buffer capacity is %d.",
|
||||||
|
input.remaining(),
|
||||||
|
buffer.capacity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
buffer.put(input);
|
||||||
|
|
||||||
|
// Submit the buffer to the codec for decoding. The presentationTimeUs
|
||||||
|
// indicates the position (play time) for the current sample.
|
||||||
|
if (crypto == null) {
|
||||||
|
mDecoder.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
|
||||||
|
} else {
|
||||||
|
mDecoder.queueSecureInputBuffer(index, 0, crypto, presentationTimeUs, flags);
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MediaCodec.CryptoInfo cryptoInfo= new MediaCodec.CryptoInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a media sample to the decoder.
|
||||||
|
*
|
||||||
|
* A "sample" here refers to a single atomic access unit in the media stream. The definition
|
||||||
|
* of "access unit" is dependent on the type of encoding used, but it typically refers to
|
||||||
|
* a single frame of video or a few seconds of audio. {@link android.media.MediaExtractor}
|
||||||
|
* extracts data from a stream one sample at a time.
|
||||||
|
*
|
||||||
|
* @param extractor Instance of {@link android.media.MediaExtractor} wrapping the media.
|
||||||
|
*
|
||||||
|
* @param presentationTimeUs The time, relative to the beginning of the media stream,
|
||||||
|
* at which this buffer should be rendered.
|
||||||
|
*
|
||||||
|
* @param flags Flags to pass to the decoder. See {@link MediaCodec#queueInputBuffer(int,
|
||||||
|
* int, int, long, int)}
|
||||||
|
*
|
||||||
|
* @throws MediaCodec.CryptoException
|
||||||
|
*/
|
||||||
|
public boolean writeSample(final MediaExtractor extractor,
|
||||||
|
final boolean isSecure,
|
||||||
|
final long presentationTimeUs,
|
||||||
|
int flags) {
|
||||||
|
boolean result = false;
|
||||||
|
boolean isEos = false;
|
||||||
|
|
||||||
|
if (!mAvailableInputBuffers.isEmpty()) {
|
||||||
|
int index = mAvailableInputBuffers.remove();
|
||||||
|
ByteBuffer buffer = mInputBuffers[index];
|
||||||
|
|
||||||
|
// reads the sample from the file using extractor into the buffer
|
||||||
|
int size = extractor.readSampleData(buffer, 0);
|
||||||
|
if (size <= 0) {
|
||||||
|
flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit the buffer to the codec for decoding. The presentationTimeUs
|
||||||
|
// indicates the position (play time) for the current sample.
|
||||||
|
if (!isSecure) {
|
||||||
|
mDecoder.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
|
||||||
|
} else {
|
||||||
|
extractor.getSampleCryptoInfo(cryptoInfo);
|
||||||
|
mDecoder.queueSecureInputBuffer(index, 0, cryptoInfo, presentationTimeUs, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a peek() operation in the queue to extract media info for the buffer ready to be
|
||||||
|
* released i.e. the head element of the queue.
|
||||||
|
*
|
||||||
|
* @param out_bufferInfo An output var to hold the buffer info.
|
||||||
|
*
|
||||||
|
* @return True, if the peek was successful.
|
||||||
|
*/
|
||||||
|
public boolean peekSample(MediaCodec.BufferInfo out_bufferInfo) {
|
||||||
|
// dequeue available buffers and synchronize our data structures with the codec.
|
||||||
|
update();
|
||||||
|
boolean result = false;
|
||||||
|
if (!mAvailableOutputBuffers.isEmpty()) {
|
||||||
|
int index = mAvailableOutputBuffers.peek();
|
||||||
|
MediaCodec.BufferInfo info = mOutputBufferInfo[index];
|
||||||
|
// metadata of the sample
|
||||||
|
out_bufferInfo.set(
|
||||||
|
info.offset,
|
||||||
|
info.size,
|
||||||
|
info.presentationTimeUs,
|
||||||
|
info.flags);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes, releases and optionally renders the output buffer available at the head of the
|
||||||
|
* queue. All observers are notified with a callback. See {@link
|
||||||
|
* OutputSampleListener#outputSample(MediaCodecWrapper, android.media.MediaCodec.BufferInfo,
|
||||||
|
* java.nio.ByteBuffer)}
|
||||||
|
*
|
||||||
|
* @param render True, if the buffer is to be rendered on the {@link Surface} configured
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void popSample(boolean render) {
|
||||||
|
// dequeue available buffers and synchronize our data structures with the codec.
|
||||||
|
update();
|
||||||
|
if (!mAvailableOutputBuffers.isEmpty()) {
|
||||||
|
int index = mAvailableOutputBuffers.remove();
|
||||||
|
|
||||||
|
if (render && mOutputSampleListener != null) {
|
||||||
|
ByteBuffer buffer = mOutputBuffers[index];
|
||||||
|
MediaCodec.BufferInfo info = mOutputBufferInfo[index];
|
||||||
|
mOutputSampleListener.outputSample(this, info, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// releases the buffer back to the codec
|
||||||
|
mDecoder.releaseOutputBuffer(index, render);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize this object's state with the internal state of the wrapped
|
||||||
|
* MediaCodec.
|
||||||
|
*/
|
||||||
|
private void update() {
|
||||||
|
// BEGIN_INCLUDE(update_codec_state)
|
||||||
|
int index;
|
||||||
|
|
||||||
|
// Get valid input buffers from the codec to fill later in the same order they were
|
||||||
|
// made available by the codec.
|
||||||
|
while ((index = mDecoder.dequeueInputBuffer(0)) != MediaCodec.INFO_TRY_AGAIN_LATER) {
|
||||||
|
mAvailableInputBuffers.add(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Likewise with output buffers. If the output buffers have changed, start using the
|
||||||
|
// new set of output buffers. If the output format has changed, notify listeners.
|
||||||
|
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
|
||||||
|
while ((index = mDecoder.dequeueOutputBuffer(info, 0)) != MediaCodec.INFO_TRY_AGAIN_LATER) {
|
||||||
|
switch (index) {
|
||||||
|
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
|
||||||
|
mOutputBuffers = mDecoder.getOutputBuffers();
|
||||||
|
mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
|
||||||
|
mAvailableOutputBuffers.clear();
|
||||||
|
break;
|
||||||
|
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
|
||||||
|
if (mOutputFormatChangedListener != null) {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mOutputFormatChangedListener
|
||||||
|
.outputFormatChanged(MediaCodecWrapper.this,
|
||||||
|
mDecoder.getOutputFormat());
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Making sure the index is valid before adding to output buffers. We've already
|
||||||
|
// handled INFO_TRY_AGAIN_LATER, INFO_OUTPUT_FORMAT_CHANGED &
|
||||||
|
// INFO_OUTPUT_BUFFERS_CHANGED i.e all the other possible return codes but
|
||||||
|
// asserting index value anyways for future-proofing the code.
|
||||||
|
if(index >= 0) {
|
||||||
|
mOutputBufferInfo[index] = info;
|
||||||
|
mAvailableOutputBuffers.add(index);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unknown status from dequeueOutputBuffer");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// END_INCLUDE(update_codec_state)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WriteException extends Throwable {
|
||||||
|
private WriteException(final String detailMessage) {
|
||||||
|
super(detailMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<!--
|
||||||
|
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.Holo.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>
|
||||||
51
samples/browseable/BatchStepSensor/AndroidManifest.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.android.batchstepsensor"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
<!-- This sample requires at least Android KitKat for sensor batching support -->
|
||||||
|
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
|
||||||
|
|
||||||
|
<!-- Require the step counter and step detector sensors.
|
||||||
|
See the method BatchStepSensorFragment#isKitkatWithStepSensor() for a programmatic check if
|
||||||
|
support is optional and the application supports a case where these sensors are not available.
|
||||||
|
-->
|
||||||
|
<uses-feature android:name="android.hardware.sensor.stepcounter" />
|
||||||
|
<uses-feature android:name="android.hardware.sensor.stepdetector" />
|
||||||
|
|
||||||
|
|
||||||
|
<application android:allowBackup="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity android:name=".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>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
</manifest>
|
||||||
21
samples/browseable/BatchStepSensor/_index.jd
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
page.tags="BatchStepSensor"
|
||||||
|
sample.group=Sensors
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
|
This sample demonstrates the use of the two step sensors (step detector and counter) and
|
||||||
|
sensor batching.\n\n It shows how to register a SensorEventListener with and without
|
||||||
|
batching and shows how these events are received.\n\nThe Step Detector sensor fires an
|
||||||
|
event when a step is detected, while the step counter returns the total number of
|
||||||
|
steps since a listener was first registered for this sensor.
|
||||||
|
Both sensors only count steps while a listener is registered. This sample only covers the
|
||||||
|
basic case, where a listener is only registered while the app is running. Likewise,
|
||||||
|
batched sensors can be used in the background (when the CPU is suspended), which
|
||||||
|
requires manually flushing the sensor event queue before it overflows, which is not
|
||||||
|
covered in this sample.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
After Width: | Height: | Size: 438 B |
|
After Width: | Height: | Size: 4.3 KiB |
BIN
samples/browseable/BatchStepSensor/res/drawable-hdpi/tile.9.png
Normal file
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 328 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 442 B |