blob: 5cddb4f8e08d1ed79e18b612955e9eb696564728 [file] [log] [blame]
/*
* Copyright (C) 2013 DroidDriver committers
*
* 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 io.appium.droiddriver.helpers;
import android.annotation.TargetApi;
import android.app.Instrumentation;
import android.os.Build;
import java.lang.reflect.InvocationTargetException;
import io.appium.droiddriver.DroidDriver;
import io.appium.droiddriver.exceptions.DroidDriverException;
import io.appium.droiddriver.instrumentation.InstrumentationDriver;
import io.appium.droiddriver.uiautomation.UiAutomationDriver;
import io.appium.droiddriver.util.InstrumentationUtils;
/**
* Static utility methods using a singleton {@link DroidDriver} instance. This class is NOT
* required, but it is handy and using a singleton driver can avoid memory leak when you have many
* instances around (for example, one in every test - JUnit framework keeps the test instances in
* memory after running them).
*/
public class DroidDrivers {
private static DroidDriver driver;
/**
* Gets the singleton driver. Throws if {@link #setSingleton} has not been called.
*/
public static DroidDriver get() {
if (driver == null) {
throw new DroidDriverException("setSingleton() has not been called");
}
return driver;
}
/**
* Sets the singleton driver.
*/
public static void setSingleton(DroidDriver driver) {
if (DroidDrivers.driver != null) {
throw new DroidDriverException("setSingleton() can only be called once");
}
DroidDrivers.driver = driver;
}
/**
* Returns whether the running target (device or emulator) has {@link android.app.UiAutomation}
* API, which is introduced in SDK API 18 (JELLY_BEAN_MR2).
*/
public static boolean hasUiAutomation() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}
/**
* Returns a new DroidDriver instance. If am instrument options have "driver", treat it as the
* fully-qualified-class-name and create a new instance of it with {@code instrumentation} as the
* argument; otherwise a new platform-dependent default DroidDriver instance.
*/
public static DroidDriver newDriver() {
Instrumentation instrumentation = InstrumentationUtils.getInstrumentation();
String driverClass = InstrumentationUtils.getD2Option("driver");
if (driverClass != null) {
try {
return (DroidDriver) Class.forName(driverClass).getConstructor(Instrumentation.class)
.newInstance(instrumentation);
} catch (ClassNotFoundException e) {
throw new DroidDriverException(e);
} catch (NoSuchMethodException e) {
throw new DroidDriverException(e);
} catch (InstantiationException e) {
throw new DroidDriverException(e);
} catch (IllegalAccessException e) {
throw new DroidDriverException(e);
} catch (IllegalArgumentException e) {
throw new DroidDriverException(e);
} catch (InvocationTargetException e) {
throw new DroidDriverException(e);
}
}
// If "dd.driver" is not specified, return default.
if (hasUiAutomation()) {
checkUiAutomation();
return new UiAutomationDriver(instrumentation);
}
return new InstrumentationDriver(instrumentation);
}
/** Checks if UiAutomation API is available */
@TargetApi(18)
public static void checkUiAutomation() {
if (!hasUiAutomation()) {
throw new DroidDriverException("UiAutomation is not available below API 18. "
+ "See http://developer.android.com/reference/android/app/UiAutomation.html");
}
if (InstrumentationUtils.getInstrumentation().getUiAutomation() == null) {
throw new DroidDriverException(
"uiAutomation==null: did you forget to set '-w' flag for 'am instrument'?");
}
}
}