Home | History | Annotate | Download | only in helpers
      1 /*
      2  * Copyright (C) 2013 DroidDriver committers
      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 
     17 package io.appium.droiddriver.helpers;
     18 
     19 import android.annotation.TargetApi;
     20 import android.app.Instrumentation;
     21 import android.os.Build;
     22 
     23 import io.appium.droiddriver.DroidDriver;
     24 import io.appium.droiddriver.exceptions.DroidDriverException;
     25 import io.appium.droiddriver.instrumentation.InstrumentationDriver;
     26 import io.appium.droiddriver.uiautomation.UiAutomationDriver;
     27 import io.appium.droiddriver.util.InstrumentationUtils;
     28 
     29 /**
     30  * Static utility methods using a singleton {@link DroidDriver} instance. This class is NOT
     31  * required, but it is handy and using a singleton driver can avoid memory leak when you have many
     32  * instances around (for example, one in every test - JUnit framework keeps the test instances in
     33  * memory after running them).
     34  */
     35 public class DroidDrivers {
     36   private static DroidDriver driver;
     37 
     38   /**
     39    * Gets the singleton driver. Throws if {@link #setSingleton} has not been called.
     40    */
     41   public static DroidDriver get() {
     42     if (driver == null) {
     43       throw new DroidDriverException("setSingleton() has not been called");
     44     }
     45     return driver;
     46   }
     47 
     48   /**
     49    * Sets the singleton driver.
     50    */
     51   public static void setSingleton(DroidDriver driver) {
     52     if (DroidDrivers.driver != null) {
     53       throw new DroidDriverException("setSingleton() can only be called once");
     54     }
     55     DroidDrivers.driver = driver;
     56   }
     57 
     58   /**
     59    * Returns whether the running target (device or emulator) has {@link android.app.UiAutomation}
     60    * API, which is introduced in SDK API 18 (JELLY_BEAN_MR2).
     61    */
     62   public static boolean hasUiAutomation() {
     63     return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
     64   }
     65 
     66   /**
     67    * Returns a new DroidDriver instance. If am instrument options have "driver", treat it as the
     68    * fully-qualified-class-name and create a new instance of it with {@code instrumentation} as the
     69    * argument; otherwise a new platform-dependent default DroidDriver instance.
     70    */
     71   public static DroidDriver newDriver() {
     72     Instrumentation instrumentation = InstrumentationUtils.getInstrumentation();
     73     String driverClass = InstrumentationUtils.getD2Option("driver");
     74     if (driverClass != null) {
     75       try {
     76         return (DroidDriver) Class.forName(driverClass).getConstructor(Instrumentation.class)
     77             .newInstance(instrumentation);
     78       } catch (Throwable t) {
     79         throw DroidDriverException.propagate(t);
     80       }
     81     }
     82 
     83     // If "dd.driver" is not specified, return default.
     84     if (hasUiAutomation()) {
     85       checkUiAutomation();
     86       return new UiAutomationDriver(instrumentation);
     87     }
     88     return new InstrumentationDriver(instrumentation);
     89   }
     90 
     91   /** Checks if UiAutomation API is available */
     92   @TargetApi(18)
     93   public static void checkUiAutomation() {
     94     if (!hasUiAutomation()) {
     95       throw new DroidDriverException("UiAutomation is not available below API 18. "
     96           + "See http://developer.android.com/reference/android/app/UiAutomation.html");
     97     }
     98     if (InstrumentationUtils.getInstrumentation().getUiAutomation() == null) {
     99       throw new DroidDriverException(
    100           "uiAutomation==null: did you forget to set '-w' flag for 'am instrument'?");
    101     }
    102   }
    103 }
    104