1/* 2 * Copyright (C) 2017 The Android Open Source Project 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 */ 16package androidx.wear.ambient; 17 18import android.app.Activity; 19import android.os.Bundle; 20 21import androidx.annotation.RestrictTo; 22 23import com.google.android.wearable.compat.WearableActivityController; 24 25import java.lang.reflect.Method; 26 27/** 28 * Provides a {@link WearableActivityController} for ambient mode control. 29 * 30 * @hide 31 */ 32@RestrictTo(RestrictTo.Scope.LIBRARY) 33public class WearableControllerProvider { 34 35 private static final String TAG = "WearableControllerProvider"; 36 37 private static volatile boolean sAmbientCallbacksVerifiedPresent; 38 39 /** 40 * Retrieves a {@link WearableActivityController} to use for ambient mode. 41 * 42 * @param activity The {@link Activity} to be associated with the Controller. 43 * @param callback The {@link AmbientDelegate.AmbientCallback} for the Controller. 44 * @return the platform-appropriate version of the {@link WearableActivityController}. 45 */ 46 public WearableActivityController getWearableController(Activity activity, 47 final AmbientDelegate.AmbientCallback callback) { 48 SharedLibraryVersion.verifySharedLibraryPresent(); 49 50 // The AmbientCallback is an abstract class instead of an interface. 51 WearableActivityController.AmbientCallback callbackBridge = 52 new WearableActivityController.AmbientCallback() { 53 @Override 54 public void onEnterAmbient(Bundle ambientDetails) { 55 callback.onEnterAmbient(ambientDetails); 56 } 57 58 @Override 59 public void onUpdateAmbient() { 60 callback.onUpdateAmbient(); 61 } 62 63 @Override 64 public void onExitAmbient() { 65 callback.onExitAmbient(); 66 } 67 }; 68 69 verifyAmbientCallbacksPresent(); 70 71 return new WearableActivityController(TAG, activity, callbackBridge); 72 } 73 74 private static void verifyAmbientCallbacksPresent() { 75 if (sAmbientCallbacksVerifiedPresent) { 76 return; 77 } 78 try { 79 Method method = 80 WearableActivityController.AmbientCallback.class.getDeclaredMethod( 81 "onEnterAmbient", Bundle.class); 82 // Proguard is sneaky -- it will actually rewrite strings it finds in addition to 83 // function names. Therefore add a "." prefix to the method name check to ensure the 84 // function was not renamed by proguard. 85 if (!(".onEnterAmbient".equals("." + method.getName()))) { 86 throw new NoSuchMethodException(); 87 } 88 } catch (NoSuchMethodException e) { 89 throw new IllegalStateException( 90 "Could not find a required method for " 91 + "ambient support, likely due to proguard optimization. Please add " 92 + "com.google.android.wearable:wearable jar to the list of library jars" 93 + " for your project"); 94 } 95 sAmbientCallbacksVerifiedPresent = true; 96 } 97} 98