| /* |
| * Copyright (C) 2012 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.android.uiautomator.actions; |
| |
| import com.android.ddmlib.IDevice; |
| import com.android.uiautomator.DebugBridge; |
| import com.android.uiautomator.UiAutomatorHelper; |
| import com.android.uiautomator.UiAutomatorHelper.UiAutomatorException; |
| import com.android.uiautomator.UiAutomatorHelper.UiAutomatorResult; |
| import com.android.uiautomator.UiAutomatorViewer; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.List; |
| |
| public class ScreenshotAction extends Action { |
| UiAutomatorViewer mViewer; |
| |
| public ScreenshotAction(UiAutomatorViewer viewer) { |
| super("&Device Screenshot"); |
| mViewer = viewer; |
| } |
| |
| @Override |
| public ImageDescriptor getImageDescriptor() { |
| return ImageHelper.loadImageDescriptorFromResource("images/screenshot.png"); |
| } |
| |
| @Override |
| public void run() { |
| if (!DebugBridge.isInitialized()) { |
| MessageDialog.openError(mViewer.getShell(), |
| "Error obtaining Device Screenshot", |
| "Unable to connect to adb. Check if adb is installed correctly."); |
| return; |
| } |
| |
| final IDevice device = pickDevice(); |
| if (device == null) { |
| return; |
| } |
| |
| ProgressMonitorDialog dialog = new ProgressMonitorDialog(mViewer.getShell()); |
| try { |
| dialog.run(true, false, new IRunnableWithProgress() { |
| @Override |
| public void run(IProgressMonitor monitor) throws InvocationTargetException, |
| InterruptedException { |
| UiAutomatorResult result = null; |
| try { |
| result = UiAutomatorHelper.takeSnapshot(device, monitor); |
| } catch (UiAutomatorException e) { |
| monitor.done(); |
| showError(e.getMessage(), e); |
| return; |
| } |
| |
| mViewer.setModel(result.model, result.uiHierarchy, result.screenshot); |
| monitor.done(); |
| } |
| }); |
| } catch (Exception e) { |
| showError("Unexpected error while obtaining UI hierarchy", e); |
| } |
| } |
| |
| private void showError(final String msg, final Throwable t) { |
| mViewer.getShell().getDisplay().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| Status s = new Status(IStatus.ERROR, "Screenshot", msg, t); |
| ErrorDialog.openError( |
| mViewer.getShell(), "Error", "Error obtaining UI hierarchy", s); |
| } |
| }); |
| } |
| |
| private IDevice pickDevice() { |
| List<IDevice> devices = DebugBridge.getDevices(); |
| if (devices.size() == 0) { |
| MessageDialog.openError(mViewer.getShell(), |
| "Error obtaining Device Screenshot", |
| "No Android devices were detected by adb."); |
| return null; |
| } else if (devices.size() == 1) { |
| return devices.get(0); |
| } else { |
| DevicePickerDialog dlg = new DevicePickerDialog(mViewer.getShell(), devices); |
| if (dlg.open() != Window.OK) { |
| return null; |
| } |
| return dlg.getSelectedDevice(); |
| } |
| } |
| |
| private static class DevicePickerDialog extends Dialog { |
| private final List<IDevice> mDevices; |
| private final String[] mDeviceNames; |
| private static int sSelectedDeviceIndex; |
| |
| public DevicePickerDialog(Shell parentShell, List<IDevice> devices) { |
| super(parentShell); |
| |
| mDevices = devices; |
| mDeviceNames = new String[mDevices.size()]; |
| for (int i = 0; i < devices.size(); i++) { |
| mDeviceNames[i] = devices.get(i).getName(); |
| } |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parentShell) { |
| Composite parent = (Composite) super.createDialogArea(parentShell); |
| Composite c = new Composite(parent, SWT.NONE); |
| |
| c.setLayout(new GridLayout(2, false)); |
| |
| Label l = new Label(c, SWT.NONE); |
| l.setText("Select device: "); |
| |
| final Combo combo = new Combo(c, SWT.BORDER | SWT.READ_ONLY); |
| combo.setItems(mDeviceNames); |
| int defaultSelection = |
| sSelectedDeviceIndex < mDevices.size() ? sSelectedDeviceIndex : 0; |
| combo.select(defaultSelection); |
| sSelectedDeviceIndex = defaultSelection; |
| |
| combo.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent arg0) { |
| sSelectedDeviceIndex = combo.getSelectionIndex(); |
| } |
| }); |
| |
| return parent; |
| } |
| |
| public IDevice getSelectedDevice() { |
| return mDevices.get(sSelectedDeviceIndex); |
| } |
| } |
| } |