am ca789a98: Merge "docs: Code sample for game controller training class." into jb-mr2-docs
* commit 'ca789a983563ee222b9feb6409cf8ea1917040c3': docs: Code sample for game controller training class.
This commit is contained in:
29
samples/ControllerSample/AndroidManifest.xml
Normal file
29
samples/ControllerSample/AndroidManifest.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.controllersample"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="9"
|
||||||
|
android:targetSdkVersion="18" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme" >
|
||||||
|
<activity
|
||||||
|
android:name=".GameViewActivity"
|
||||||
|
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>
|
||||||
BIN
samples/ControllerSample/libs/android-support-v4.jar
Normal file
BIN
samples/ControllerSample/libs/android-support-v4.jar
Normal file
Binary file not shown.
20
samples/ControllerSample/proguard-project.txt
Normal file
20
samples/ControllerSample/proguard-project.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# To enable ProGuard in your project, edit project.properties
|
||||||
|
# to define the proguard.config property as described in that file.
|
||||||
|
#
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the ProGuard
|
||||||
|
# include property in project.properties.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
14
samples/ControllerSample/project.properties
Normal file
14
samples/ControllerSample/project.properties
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-18
|
||||||
BIN
samples/ControllerSample/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
samples/ControllerSample/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
samples/ControllerSample/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
samples/ControllerSample/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 746 B |
BIN
samples/ControllerSample/res/drawable-xhdpi/ic_launcher.png
Normal file
BIN
samples/ControllerSample/res/drawable-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
samples/ControllerSample/res/drawable-xxhdpi/ic_launcher.png
Normal file
BIN
samples/ControllerSample/res/drawable-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Game controller input demo. -->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dip"
|
||||||
|
android:text="@string/game_controller_input_description" />
|
||||||
|
|
||||||
|
<com.example.controllersample.GameView
|
||||||
|
android:id="@+id/game"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dip"
|
||||||
|
android:layout_margin="15dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="#000000" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
11
samples/ControllerSample/res/values-v11/styles.xml
Normal file
11
samples/ControllerSample/res/values-v11/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 11+. This theme completely replaces
|
||||||
|
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||||
|
<!-- API 11 theme customizations can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
12
samples/ControllerSample/res/values-v14/styles.xml
Normal file
12
samples/ControllerSample/res/values-v14/styles.xml
Normal file
@@ -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>
|
||||||
11
samples/ControllerSample/res/values/strings.xml
Normal file
11
samples/ControllerSample/res/values/strings.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Controller Sample</string>
|
||||||
|
<string name="game_controller_input_description">
|
||||||
|
This activity demonstrates how to process input events received from
|
||||||
|
game controllers. Please connect your game controller now and try
|
||||||
|
moving the joysticks or pressing buttons. If it helps, try to imagine
|
||||||
|
that you are a lone space cowboy in hot pursuit of the aliens who kidnapped
|
||||||
|
your favorite llama on their way back to Andromeda…
|
||||||
|
</string>
|
||||||
|
</resources>
|
||||||
20
samples/ControllerSample/res/values/styles.xml
Normal file
20
samples/ControllerSample/res/values/styles.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||||
|
<!--
|
||||||
|
Theme customizations available in newer API levels can go in
|
||||||
|
res/values-vXX/styles.xml, while customizations related to
|
||||||
|
backward-compatibility can go here.
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Application theme. -->
|
||||||
|
<style name="AppTheme" parent="AppBaseTheme">
|
||||||
|
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.controllersample;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class GameViewActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
this.setContentView(R.layout.game_controller_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.inputmanagercompat;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
public interface InputManagerCompat {
|
||||||
|
/**
|
||||||
|
* Gets information about the input device with the specified id.
|
||||||
|
*
|
||||||
|
* @param id The device id
|
||||||
|
* @return The input device or null if not found
|
||||||
|
*/
|
||||||
|
public InputDevice getInputDevice(int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ids of all input devices in the system.
|
||||||
|
*
|
||||||
|
* @return The input device ids.
|
||||||
|
*/
|
||||||
|
public int[] getInputDeviceIds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an input device listener to receive notifications about when
|
||||||
|
* input devices are added, removed or changed.
|
||||||
|
*
|
||||||
|
* @param listener The listener to register.
|
||||||
|
* @param handler The handler on which the listener should be invoked, or
|
||||||
|
* null if the listener should be invoked on the calling thread's
|
||||||
|
* looper.
|
||||||
|
*/
|
||||||
|
public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
|
||||||
|
Handler handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters an input device listener.
|
||||||
|
*
|
||||||
|
* @param listener The listener to unregister.
|
||||||
|
*/
|
||||||
|
public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following three calls are to simulate V16 behavior on pre-Jellybean
|
||||||
|
* devices. If you don't call them, your callback will never be called
|
||||||
|
* pre-API 16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass the motion events to the InputManagerCompat. This is used to
|
||||||
|
* optimize for polling for controllers. If you do not pass these events in,
|
||||||
|
* polling will cause regular object creation.
|
||||||
|
*
|
||||||
|
* @param event the motion event from the app
|
||||||
|
*/
|
||||||
|
public void onGenericMotionEvent(MotionEvent event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the V9 input manager that it should stop polling for disconnected
|
||||||
|
* devices. You can call this during onPause in your activity, although you
|
||||||
|
* might want to call it whenever your game is not active (or whenever you
|
||||||
|
* don't care about being notified of new input devices)
|
||||||
|
*/
|
||||||
|
public void onPause();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the V9 input manager that it should start polling for disconnected
|
||||||
|
* devices. You can call this during onResume in your activity, although you
|
||||||
|
* might want to call it less often (only when the gameplay is actually
|
||||||
|
* active)
|
||||||
|
*/
|
||||||
|
public void onResume();
|
||||||
|
|
||||||
|
public interface InputDeviceListener {
|
||||||
|
/**
|
||||||
|
* Called whenever the input manager detects that a device has been
|
||||||
|
* added. This will only be called in the V9 version when a motion event
|
||||||
|
* is detected.
|
||||||
|
*
|
||||||
|
* @param deviceId The id of the input device that was added.
|
||||||
|
*/
|
||||||
|
void onInputDeviceAdded(int deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever the properties of an input device have changed since
|
||||||
|
* they were last queried. This will not be called for the V9 version of
|
||||||
|
* the API.
|
||||||
|
*
|
||||||
|
* @param deviceId The id of the input device that changed.
|
||||||
|
*/
|
||||||
|
void onInputDeviceChanged(int deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever the input manager detects that a device has been
|
||||||
|
* removed. For the V9 version, this can take some time depending on the
|
||||||
|
* poll rate.
|
||||||
|
*
|
||||||
|
* @param deviceId The id of the input device that was removed.
|
||||||
|
*/
|
||||||
|
void onInputDeviceRemoved(int deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to construct a compatible InputManager.
|
||||||
|
*/
|
||||||
|
public static class Factory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs and returns a compatible InputManger
|
||||||
|
*
|
||||||
|
* @param context the Context that will be used to get the system
|
||||||
|
* service from
|
||||||
|
* @return a compatible implementation of InputManager
|
||||||
|
*/
|
||||||
|
public static InputManagerCompat getInputManager(Context context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
return new InputManagerV16(context);
|
||||||
|
} else {
|
||||||
|
return new InputManagerV9();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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.inputmanagercompat;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.input.InputManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
|
public class InputManagerV16 implements InputManagerCompat {
|
||||||
|
|
||||||
|
private final InputManager mInputManager;
|
||||||
|
private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
|
||||||
|
|
||||||
|
public InputManagerV16(Context context) {
|
||||||
|
mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
|
||||||
|
mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputDevice getInputDevice(int id) {
|
||||||
|
return mInputManager.getInputDevice(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getInputDeviceIds() {
|
||||||
|
return mInputManager.getInputDeviceIds();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class V16InputDeviceListener implements InputManager.InputDeviceListener {
|
||||||
|
final InputManagerCompat.InputDeviceListener mIDL;
|
||||||
|
|
||||||
|
public V16InputDeviceListener(InputDeviceListener idl) {
|
||||||
|
mIDL = idl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceAdded(int deviceId) {
|
||||||
|
mIDL.onInputDeviceAdded(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceChanged(int deviceId) {
|
||||||
|
mIDL.onInputDeviceChanged(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceRemoved(int deviceId) {
|
||||||
|
mIDL.onInputDeviceRemoved(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||||
|
V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
|
||||||
|
mInputManager.registerInputDeviceListener(v16Listener, handler);
|
||||||
|
mListeners.put(listener, v16Listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||||
|
V16InputDeviceListener curListener = mListeners.remove(listener);
|
||||||
|
if (null != curListener)
|
||||||
|
{
|
||||||
|
mInputManager.unregisterInputDeviceListener(curListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGenericMotionEvent(MotionEvent event) {
|
||||||
|
// unused in V16
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
// unused in V16
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
// unused in V16
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* 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.inputmanagercompat;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
public class InputManagerV9 implements InputManagerCompat {
|
||||||
|
private static final String LOG_TAG = "InputManagerV9";
|
||||||
|
private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
|
||||||
|
private static final long CHECK_ELAPSED_TIME = 3000L;
|
||||||
|
|
||||||
|
private static final int ON_DEVICE_ADDED = 0;
|
||||||
|
private static final int ON_DEVICE_CHANGED = 1;
|
||||||
|
private static final int ON_DEVICE_REMOVED = 2;
|
||||||
|
|
||||||
|
private final SparseArray<long[]> mDevices;
|
||||||
|
private final Map<InputDeviceListener, Handler> mListeners;
|
||||||
|
private final Handler mDefaultHandler;
|
||||||
|
|
||||||
|
private static class PollingMessageHandler extends Handler {
|
||||||
|
private final WeakReference<InputManagerV9> mInputManager;
|
||||||
|
|
||||||
|
PollingMessageHandler(InputManagerV9 im) {
|
||||||
|
mInputManager = new WeakReference<InputManagerV9>(im);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
super.handleMessage(msg);
|
||||||
|
switch (msg.what) {
|
||||||
|
case MESSAGE_TEST_FOR_DISCONNECT:
|
||||||
|
InputManagerV9 imv = mInputManager.get();
|
||||||
|
if (null != imv) {
|
||||||
|
long time = SystemClock.elapsedRealtime();
|
||||||
|
int size = imv.mDevices.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
long[] lastContact = imv.mDevices.valueAt(i);
|
||||||
|
if (null != lastContact) {
|
||||||
|
if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
|
||||||
|
// check to see if the device has been
|
||||||
|
// disconnected
|
||||||
|
int id = imv.mDevices.keyAt(i);
|
||||||
|
if (null == InputDevice.getDevice(id)) {
|
||||||
|
// disconnected!
|
||||||
|
imv.notifyListeners(ON_DEVICE_REMOVED, id);
|
||||||
|
imv.mDevices.remove(id);
|
||||||
|
} else {
|
||||||
|
lastContact[0] = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
|
||||||
|
CHECK_ELAPSED_TIME);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputManagerV9() {
|
||||||
|
mDevices = new SparseArray<long[]>();
|
||||||
|
mListeners = new HashMap<InputDeviceListener, Handler>();
|
||||||
|
mDefaultHandler = new PollingMessageHandler(this);
|
||||||
|
// as a side-effect, populates our collection of watched
|
||||||
|
// input devices
|
||||||
|
getInputDeviceIds();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputDevice getInputDevice(int id) {
|
||||||
|
return InputDevice.getDevice(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getInputDeviceIds() {
|
||||||
|
// add any hitherto unknown devices to our
|
||||||
|
// collection of watched input devices
|
||||||
|
int[] activeDevices = InputDevice.getDeviceIds();
|
||||||
|
long time = SystemClock.elapsedRealtime();
|
||||||
|
for ( int id : activeDevices ) {
|
||||||
|
long[] lastContact = mDevices.get(id);
|
||||||
|
if ( null == lastContact ) {
|
||||||
|
// we have a new device
|
||||||
|
mDevices.put(id, new long[] { time });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activeDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
if (handler == null) {
|
||||||
|
handler = mDefaultHandler;
|
||||||
|
}
|
||||||
|
mListeners.put(listener, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyListeners(int why, int deviceId) {
|
||||||
|
// the state of some device has changed
|
||||||
|
if (!mListeners.isEmpty()) {
|
||||||
|
// yes... this will cause an object to get created... hopefully
|
||||||
|
// it won't happen very often
|
||||||
|
for (InputDeviceListener listener : mListeners.keySet()) {
|
||||||
|
Handler handler = mListeners.get(listener);
|
||||||
|
DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
|
||||||
|
handler.post(odc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DeviceEvent implements Runnable {
|
||||||
|
private int mMessageType;
|
||||||
|
private int mId;
|
||||||
|
private InputDeviceListener mListener;
|
||||||
|
private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
|
||||||
|
|
||||||
|
private DeviceEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeviceEvent getDeviceEvent(int messageType, int id,
|
||||||
|
InputDeviceListener listener) {
|
||||||
|
DeviceEvent curChanged = sEventQueue.poll();
|
||||||
|
if (null == curChanged) {
|
||||||
|
curChanged = new DeviceEvent();
|
||||||
|
}
|
||||||
|
curChanged.mMessageType = messageType;
|
||||||
|
curChanged.mId = id;
|
||||||
|
curChanged.mListener = listener;
|
||||||
|
return curChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
switch (mMessageType) {
|
||||||
|
case ON_DEVICE_ADDED:
|
||||||
|
mListener.onInputDeviceAdded(mId);
|
||||||
|
break;
|
||||||
|
case ON_DEVICE_CHANGED:
|
||||||
|
mListener.onInputDeviceChanged(mId);
|
||||||
|
break;
|
||||||
|
case ON_DEVICE_REMOVED:
|
||||||
|
mListener.onInputDeviceRemoved(mId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(LOG_TAG, "Unknown Message Type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// dump this runnable back in the queue
|
||||||
|
sEventQueue.offer(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGenericMotionEvent(MotionEvent event) {
|
||||||
|
// detect new devices
|
||||||
|
int id = event.getDeviceId();
|
||||||
|
long[] timeArray = mDevices.get(id);
|
||||||
|
if (null == timeArray) {
|
||||||
|
notifyListeners(ON_DEVICE_ADDED, id);
|
||||||
|
timeArray = new long[1];
|
||||||
|
mDevices.put(id, timeArray);
|
||||||
|
}
|
||||||
|
long time = SystemClock.elapsedRealtime();
|
||||||
|
timeArray[0] = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user