• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

development


コミットメタ情報

リビジョン42d3a4ae1431fb3f02ac212000e8cdfb6f21e226 (tree)
日時2010-09-14 09:00:10
作者Megha Joshi <mjoshi@goog...>
コミッターMegha Joshi

ログメッセージ

Adding CrossCompatibility sample app.

Change-Id: I565584ea53212f61a9fbbb44e50da59f4ba06fff

変更サマリ

差分

--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -109,6 +109,7 @@ development/samples/CubeLiveWallpaper samples/${PLATFORM_NAME}/CubeLiveWa
109109 development/samples/VoiceRecognitionService samples/${PLATFORM_NAME}/VoiceRecognitionService
110110 development/samples/TicTacToeLib samples/${PLATFORM_NAME}/TicTacToeLib
111111 development/samples/TicTacToeMain samples/${PLATFORM_NAME}/TicTacToeMain
112+development/samples/CrossCompatibility samples/${PLATFORM_NAME}/CrossCompatibility
112113
113114 # dx
114115 bin/dx platforms/${PLATFORM_NAME}/tools/dx
--- /dev/null
+++ b/samples/CrossCompatibility/AndroidManifest.xml
@@ -0,0 +1,17 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+ package="com.example.android.touchexample"
4+ android:versionCode="1"
5+ android:versionName="1.0">
6+ <application android:icon="@drawable/icon" android:label="@string/app_name">
7+ <activity android:name=".TouchExampleActivity"
8+ android:label="@string/app_name">
9+ <intent-filter>
10+ <action android:name="android.intent.action.MAIN" />
11+ <category android:name="android.intent.category.LAUNCHER" />
12+ </intent-filter>
13+ </activity>
14+
15+ </application>
16+ <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8" />
17+</manifest>
--- /dev/null
+++ b/samples/CrossCompatibility/_index.html
@@ -0,0 +1,20 @@
1+<p>This sample demonstrates how to design an application that is compatible across different Android versions. Applications
2+should degrade gracefully on older platform versions, dropping features or providing
3+when the platform support needed by features or functionality isn't available.</p>
4+
5+<p>In this case, the CrossCompatibility application shows how to use APIs that are not available in all Android versions and
6+still create a single <code>.apk</code> that runs on all Android versions.</p>
7+
8+<ul>
9+<li>The main application's <a
10+href="AndroidManifest.html">AndroidManifest.xml</a> file declares that it is backwards compatible with API level 3 devices with attribute <code>minSdkVersion</code> in the <code>uses-sdk</code> tag.
11+ </li>
12+<li>
13+<a
14+href="src/com/example/android/touchexample/VersionedGestureDetector.html">VersionedGestureDetector.java</a>
15+is a version independent abstract class which factors out multitouch APIs that differ between platform versions. </li>
16+
17+</ul>
18+
19+<p> For more information on how to make your applications cross-compatible, please check out the original
20+blogpost <a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">here</a>.</p>
--- /dev/null
+++ b/samples/CrossCompatibility/build.xml
@@ -0,0 +1,67 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<project name="TouchExampleActivity" default="help">
3+
4+ <!-- The local.properties file is created and updated by the 'android' tool.
5+ It contains the path to the SDK. It should *NOT* be checked in in Version
6+ Control Systems. -->
7+ <property file="local.properties" />
8+
9+ <!-- The build.properties file can be created by you and is never touched
10+ by the 'android' tool. This is the place to change some of the default property values
11+ used by the Ant rules.
12+ Here are some properties you may want to change/update:
13+
14+ application.package
15+ the name of your application package as defined in the manifest. Used by the
16+ 'uninstall' rule.
17+ source.dir
18+ the name of the source directory. Default is 'src'.
19+ out.dir
20+ the name of the output directory. Default is 'bin'.
21+
22+ Properties related to the SDK location or the project target should be updated
23+ using the 'android' tool with the 'update' action.
24+
25+ This file is an integral part of the build system for your application and
26+ should be checked in in Version Control Systems.
27+
28+ -->
29+ <property file="build.properties" />
30+
31+ <!-- The default.properties file is created and updated by the 'android' tool, as well
32+ as ADT.
33+ This file is an integral part of the build system for your application and
34+ should be checked in in Version Control Systems. -->
35+ <property file="default.properties" />
36+
37+ <!-- Custom Android task to deal with the project target, and import the proper rules.
38+ This requires ant 1.6.0 or above. -->
39+ <path id="android.antlibs">
40+ <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
41+ <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
42+ <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
43+ <pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
44+ <pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
45+ </path>
46+
47+ <taskdef name="setup"
48+ classname="com.android.ant.SetupTask"
49+ classpathref="android.antlibs" />
50+
51+ <!-- Execute the Android Setup task that will setup some properties specific to the target,
52+ and import the build rules files.
53+
54+ The rules file is imported from
55+ <SDK>/platforms/<target_platform>/templates/android_rules.xml
56+
57+ To customize some build steps for your project:
58+ - copy the content of the main node <project> from android_rules.xml
59+ - paste it in this build.xml below the <setup /> task.
60+ - disable the import by changing the setup task below to <setup import="false" />
61+
62+ This will ensure that the properties are setup correctly but that your customized
63+ build steps are used.
64+ -->
65+ <setup />
66+
67+</project>
Binary files /dev/null and b/samples/CrossCompatibility/res/drawable-hdpi/icon.png differ
Binary files /dev/null and b/samples/CrossCompatibility/res/drawable-ldpi/icon.png differ
Binary files /dev/null and b/samples/CrossCompatibility/res/drawable-mdpi/icon.png differ
Binary files /dev/null and b/samples/CrossCompatibility/res/drawable/icon.png differ
--- /dev/null
+++ b/samples/CrossCompatibility/res/values/strings.xml
@@ -0,0 +1,4 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <string name="app_name">TouchExample</string>
4+</resources>
--- /dev/null
+++ b/samples/CrossCompatibility/src/com/example/android/touchexample/TouchExampleActivity.java
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package com.example.android.touchexample;
17+
18+import android.app.Activity;
19+import android.os.Bundle;
20+import android.view.ViewGroup;
21+
22+public class TouchExampleActivity extends Activity {
23+ /** Called when the activity is first created. */
24+ @Override
25+ public void onCreate(Bundle savedInstanceState) {
26+ super.onCreate(savedInstanceState);
27+
28+ TouchExampleView view = new TouchExampleView(this);
29+ view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
30+ ViewGroup.LayoutParams.MATCH_PARENT));
31+
32+ setContentView(view);
33+ }
34+}
--- /dev/null
+++ b/samples/CrossCompatibility/src/com/example/android/touchexample/TouchExampleView.java
@@ -0,0 +1,82 @@
1+/*
2+ * Copyright (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package com.example.android.touchexample;
17+
18+import android.content.Context;
19+import android.graphics.Canvas;
20+import android.graphics.drawable.Drawable;
21+import android.util.AttributeSet;
22+import android.view.MotionEvent;
23+import android.view.View;
24+
25+public class TouchExampleView extends View {
26+ private Drawable mIcon;
27+ private float mPosX;
28+ private float mPosY;
29+
30+ private VersionedGestureDetector mDetector;
31+ private float mScaleFactor = 1.f;
32+
33+ public TouchExampleView(Context context) {
34+ this(context, null, 0);
35+ }
36+
37+ public TouchExampleView(Context context, AttributeSet attrs) {
38+ this(context, attrs, 0);
39+ }
40+
41+ public TouchExampleView(Context context, AttributeSet attrs, int defStyle) {
42+ super(context, attrs, defStyle);
43+ mIcon = context.getResources().getDrawable(R.drawable.icon);
44+ mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());
45+
46+ mDetector = VersionedGestureDetector.newInstance(context, new GestureCallback());
47+ }
48+
49+ @Override
50+ public boolean onTouchEvent(MotionEvent ev) {
51+ mDetector.onTouchEvent(ev);
52+ return true;
53+ }
54+
55+ @Override
56+ public void onDraw(Canvas canvas) {
57+ super.onDraw(canvas);
58+
59+ canvas.save();
60+ canvas.translate(mPosX, mPosY);
61+ canvas.scale(mScaleFactor, mScaleFactor);
62+ mIcon.draw(canvas);
63+ canvas.restore();
64+ }
65+
66+ private class GestureCallback implements VersionedGestureDetector.OnGestureListener {
67+ public void onDrag(float dx, float dy) {
68+ mPosX += dx;
69+ mPosY += dy;
70+ invalidate();
71+ }
72+
73+ public void onScale(float scaleFactor) {
74+ mScaleFactor *= scaleFactor;
75+
76+ // Don't let the object get too small or too large.
77+ mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
78+
79+ invalidate();
80+ }
81+ }
82+}
--- /dev/null
+++ b/samples/CrossCompatibility/src/com/example/android/touchexample/VersionedGestureDetector.java
@@ -0,0 +1,165 @@
1+/*
2+ * Copyright (C) 2010 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package com.example.android.touchexample;
17+
18+import android.content.Context;
19+import android.os.Build;
20+import android.util.Log;
21+import android.view.MotionEvent;
22+import android.view.ScaleGestureDetector;
23+
24+public abstract class VersionedGestureDetector {
25+ private static final String TAG = "VersionedGestureDetector";
26+
27+ OnGestureListener mListener;
28+
29+ public static VersionedGestureDetector newInstance(Context context,
30+ OnGestureListener listener) {
31+ final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
32+ VersionedGestureDetector detector = null;
33+ if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
34+ detector = new CupcakeDetector();
35+ } else if (sdkVersion < Build.VERSION_CODES.FROYO) {
36+ detector = new EclairDetector();
37+ } else {
38+ detector = new FroyoDetector(context);
39+ }
40+
41+ Log.d(TAG, "Created new " + detector.getClass());
42+ detector.mListener = listener;
43+
44+ return detector;
45+ }
46+
47+ public abstract boolean onTouchEvent(MotionEvent ev);
48+
49+ public interface OnGestureListener {
50+ public void onDrag(float dx, float dy);
51+ public void onScale(float scaleFactor);
52+ }
53+
54+ private static class CupcakeDetector extends VersionedGestureDetector {
55+ float mLastTouchX;
56+ float mLastTouchY;
57+
58+ float getActiveX(MotionEvent ev) {
59+ return ev.getX();
60+ }
61+
62+ float getActiveY(MotionEvent ev) {
63+ return ev.getY();
64+ }
65+
66+ boolean shouldDrag() {
67+ return true;
68+ }
69+
70+ @Override
71+ public boolean onTouchEvent(MotionEvent ev) {
72+ switch (ev.getAction()) {
73+ case MotionEvent.ACTION_DOWN: {
74+ mLastTouchX = getActiveX(ev);
75+ mLastTouchY = getActiveY(ev);
76+ break;
77+ }
78+ case MotionEvent.ACTION_MOVE: {
79+ final float x = getActiveX(ev);
80+ final float y = getActiveY(ev);
81+
82+ if (shouldDrag()) {
83+ mListener.onDrag(x - mLastTouchX, y - mLastTouchY);
84+ }
85+
86+ mLastTouchX = x;
87+ mLastTouchY = y;
88+ break;
89+ }
90+ }
91+ return true;
92+ }
93+ }
94+
95+ private static class EclairDetector extends CupcakeDetector {
96+ private static final int INVALID_POINTER_ID = -1;
97+ private int mActivePointerId = INVALID_POINTER_ID;
98+ private int mActivePointerIndex = 0;
99+
100+ @Override
101+ float getActiveX(MotionEvent ev) {
102+ return ev.getX(mActivePointerIndex);
103+ }
104+
105+ @Override
106+ float getActiveY(MotionEvent ev) {
107+ return ev.getY(mActivePointerIndex);
108+ }
109+
110+ @Override
111+ public boolean onTouchEvent(MotionEvent ev) {
112+ final int action = ev.getAction();
113+ switch (action & MotionEvent.ACTION_MASK) {
114+ case MotionEvent.ACTION_DOWN:
115+ mActivePointerId = ev.getPointerId(0);
116+ break;
117+ case MotionEvent.ACTION_CANCEL:
118+ case MotionEvent.ACTION_UP:
119+ mActivePointerId = INVALID_POINTER_ID;
120+ break;
121+ case MotionEvent.ACTION_POINTER_UP:
122+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
123+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
124+ final int pointerId = ev.getPointerId(pointerIndex);
125+ if (pointerId == mActivePointerId) {
126+ // This was our active pointer going up. Choose a new
127+ // active pointer and adjust accordingly.
128+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
129+ mActivePointerId = ev.getPointerId(newPointerIndex);
130+ mLastTouchX = ev.getX(newPointerIndex);
131+ mLastTouchY = ev.getY(newPointerIndex);
132+ }
133+ break;
134+ }
135+
136+ mActivePointerIndex = ev.findPointerIndex(mActivePointerId);
137+ return super.onTouchEvent(ev);
138+ }
139+ }
140+
141+ private static class FroyoDetector extends EclairDetector {
142+ private ScaleGestureDetector mDetector;
143+
144+ public FroyoDetector(Context context) {
145+ mDetector = new ScaleGestureDetector(context,
146+ new ScaleGestureDetector.SimpleOnScaleGestureListener() {
147+ @Override public boolean onScale(ScaleGestureDetector detector) {
148+ mListener.onScale(detector.getScaleFactor());
149+ return true;
150+ }
151+ });
152+ }
153+
154+ @Override
155+ boolean shouldDrag() {
156+ return !mDetector.isInProgress();
157+ }
158+
159+ @Override
160+ public boolean onTouchEvent(MotionEvent ev) {
161+ mDetector.onTouchEvent(ev);
162+ return super.onTouchEvent(ev);
163+ }
164+ }
165+}