Add sample magnification controller service
Bug: 22718911 Change-Id: I25d2ca95836f7fe033accf215fd925fd06505b12
This commit is contained in:
@@ -662,6 +662,16 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name=".accessibility.MagnificationService"
|
||||
android:label="@string/magnification_service_label"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.accessibilityservice"
|
||||
android:resource="@xml/magnification_service" />
|
||||
</service>
|
||||
|
||||
<activity android:name=".accessibility.TaskListActivity"
|
||||
android:label="@string/accessibility_query_window"
|
||||
android:enabled="@bool/atLeastIceCreamSandwich">
|
||||
|
||||
@@ -1527,6 +1527,9 @@
|
||||
<string name="accessibility_custom_on">On</string>
|
||||
<string name="accessibility_custom_off">Off</string>
|
||||
|
||||
<string name="magnification_service_label">Magnification</string>
|
||||
<string name="magnification_service_description">Allows the volume keys to control display magnification</string>
|
||||
|
||||
<string name="task_name">Task</string>
|
||||
<string name="task_complete_template">Task %1$s %2$s</string>
|
||||
<string name="task_complete">is complete</string>
|
||||
|
||||
23
samples/ApiDemos/res/xml/magnification_service.xml
Normal file
23
samples/ApiDemos/res/xml/magnification_service.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
|
||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accessibilityEventTypes=""
|
||||
android:accessibilityFeedbackType="feedbackVisual"
|
||||
android:canRequestFilterKeyEvents="true"
|
||||
android:canControlMagnification="true"
|
||||
android:description="@string/magnification_service_description" />
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.apis.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.graphics.Region;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
/**
|
||||
* This class is an {@link AccessibilityService} that controls the state of
|
||||
* display magnification in response to key events. It demonstrates the
|
||||
* following key features of the Android accessibility APIs:
|
||||
* <ol>
|
||||
* <li>Basic implementation of an AccessibilityService
|
||||
* <li>Observing and respond to user-generated key events
|
||||
* <li>Querying and modifying the state of display magnification
|
||||
* </ol>
|
||||
*/
|
||||
public class MagnificationService extends AccessibilityService {
|
||||
private static final String LOG_TAG = "MagnificationService";
|
||||
|
||||
/**
|
||||
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
|
||||
*
|
||||
* @param event An event.
|
||||
*/
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
// No events required for this service.
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for interrupting the accessibility feedback.
|
||||
*/
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
// No interruptible actions taken by this service.
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that allows an accessibility service to observe the key events
|
||||
* before they are passed to the rest of the system. This means that the events
|
||||
* are first delivered here before they are passed to the device policy, the
|
||||
* input method, or applications.
|
||||
* <p>
|
||||
* <strong>Note:</strong> It is important that key events are handled in such
|
||||
* a way that the event stream that would be passed to the rest of the system
|
||||
* is well-formed. For example, handling the down event but not the up event
|
||||
* and vice versa would generate an inconsistent event stream.
|
||||
* </p>
|
||||
* <p>
|
||||
* <strong>Note:</strong> The key events delivered in this method are copies
|
||||
* and modifying them will have no effect on the events that will be passed
|
||||
* to the system. This method is intended to perform purely filtering
|
||||
* functionality.
|
||||
* <p>
|
||||
*
|
||||
* @param event The event to be processed.
|
||||
* @return If true then the event will be consumed and not delivered to
|
||||
* applications, otherwise it will be delivered as usual.
|
||||
*/
|
||||
@Override
|
||||
protected boolean onKeyEvent(KeyEvent event) {
|
||||
// Only consume volume key events.
|
||||
final int keyCode = event.getKeyCode();
|
||||
if (keyCode != KeyEvent.KEYCODE_VOLUME_UP
|
||||
&& keyCode != KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle the event when the user releases the volume key. To prevent
|
||||
// the keys from actually adjusting the device volume, we'll ignore
|
||||
// the result of handleVolumeKey() and always return true to consume
|
||||
// the events.
|
||||
final int action = event.getAction();
|
||||
if (action == KeyEvent.ACTION_UP) {
|
||||
handleVolumeKey(keyCode == KeyEvent.KEYCODE_VOLUME_UP);
|
||||
}
|
||||
|
||||
// Consume all volume key events.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the magnification scale in response to volume key actions.
|
||||
*
|
||||
* @param isVolumeUp {@code true} if the volume up key was pressed or
|
||||
* {@code false} if the volume down key was pressed
|
||||
* @return {@code true} if the magnification scale changed as a result of
|
||||
* the key
|
||||
*/
|
||||
private boolean handleVolumeKey(boolean isVolumeUp) {
|
||||
// Obtain the controller on-demand, which allows us to avoid
|
||||
// dependencies on the accessibility service's lifecycle.
|
||||
final MagnificationController controller = getMagnificationController();
|
||||
|
||||
// Adjust the current scale based on which volume key was pressed,
|
||||
// constraining the scale between 1x and 5x.
|
||||
final float currScale = controller.getScale();
|
||||
final float increment = isVolumeUp ? 0.1f : -0.1f;
|
||||
final float nextScale = Math.max(1f, Math.min(5f, currScale + increment));
|
||||
if (nextScale == currScale) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the pivot, then scale around it.
|
||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||
controller.setScale(nextScale, true /* animate */);
|
||||
controller.setCenter(metrics.widthPixels / 2f, metrics.heightPixels / 2f, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a part of the {@link AccessibilityService} lifecycle and is
|
||||
* called after the system has successfully bound to the service. If is
|
||||
* convenient to use this method for setting the {@link AccessibilityServiceInfo}.
|
||||
*
|
||||
* @see AccessibilityServiceInfo
|
||||
* @see #setServiceInfo(AccessibilityServiceInfo)
|
||||
*/
|
||||
@Override
|
||||
public void onServiceConnected() {
|
||||
final AccessibilityServiceInfo info = getServiceInfo();
|
||||
if (info == null) {
|
||||
// If we fail to obtain the service info, the service is not really
|
||||
// connected and we should avoid setting anything up.
|
||||
return;
|
||||
}
|
||||
|
||||
// We declared our intent to request key filtering in the meta-data
|
||||
// attached to our service in the manifest. Now, we can explicitly
|
||||
// turn on key filtering when needed.
|
||||
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;
|
||||
setServiceInfo(info);
|
||||
|
||||
// Set up a listener for changes in the state of magnification.
|
||||
getMagnificationController().addListener(new OnMagnificationChangedListener() {
|
||||
@Override
|
||||
public void onMagnificationChanged(MagnificationController controller,
|
||||
Region region, float scale, float centerX, float centerY) {
|
||||
Log.e(LOG_TAG, "Magnification scale is now " + scale);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user