1/* 2 * Copyright 2018 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 */ 16 17package androidx.core.app; 18 19import static androidx.core.app.CoreComponentFactory.checkCompatWrapper; 20 21import android.app.Activity; 22import android.app.Application; 23import android.app.Service; 24import android.content.BroadcastReceiver; 25import android.content.ContentProvider; 26import android.content.Intent; 27 28import androidx.annotation.NonNull; 29import androidx.annotation.Nullable; 30import androidx.annotation.RequiresApi; 31 32import java.lang.reflect.InvocationTargetException; 33 34/** 35 * Version of {@link android.app.AppComponentFactory} that works with androidx libraries. 36 * 37 * Note: This will only work on API 28+ and does not backport AppComponentFactory functionality. 38 */ 39@RequiresApi(28) 40public class AppComponentFactory extends android.app.AppComponentFactory { 41 42 /** 43 * @see #instantiateActivityCompat 44 */ 45 @Override 46 public final Activity instantiateActivity(ClassLoader cl, String className, Intent intent) 47 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 48 return checkCompatWrapper(instantiateActivityCompat(cl, className, intent)); 49 } 50 51 /** 52 * @see #instantiateApplicationCompat 53 */ 54 @Override 55 public final Application instantiateApplication(ClassLoader cl, String className) 56 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 57 return checkCompatWrapper(instantiateApplicationCompat(cl, className)); 58 } 59 60 /** 61 * @see #instantiateReceiverCompat 62 */ 63 @Override 64 public final BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, 65 Intent intent) 66 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 67 return checkCompatWrapper(instantiateReceiverCompat(cl, className, intent)); 68 } 69 70 /** 71 * @see #instantiateProviderCompat 72 */ 73 @Override 74 public final ContentProvider instantiateProvider(ClassLoader cl, String className) 75 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 76 return checkCompatWrapper(instantiateProviderCompat(cl, className)); 77 } 78 79 /** 80 * @see #instantiateServiceCompat 81 */ 82 @Override 83 public final Service instantiateService(ClassLoader cl, String className, Intent intent) 84 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 85 return checkCompatWrapper(instantiateServiceCompat(cl, className, intent)); 86 } 87 88 /** 89 * Allows application to override the creation of the application object. This can be used to 90 * perform things such as dependency injection or class loader changes to these 91 * classes. 92 * <p> 93 * This method is only intended to provide a hook for instantiation. It does not provide 94 * earlier access to the Application object. The returned object will not be initialized 95 * as a Context yet and should not be used to interact with other android APIs. 96 * 97 * @param cl The default classloader to use for instantiation. 98 * @param className The class to be instantiated. 99 */ 100 public @NonNull Application instantiateApplicationCompat(@NonNull ClassLoader cl, 101 @NonNull String className) 102 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 103 try { 104 return (Application) cl.loadClass(className).getDeclaredConstructor().newInstance(); 105 } catch (InvocationTargetException | NoSuchMethodException e) { 106 throw new RuntimeException("Couldn't call constructor", e); 107 } 108 } 109 110 /** 111 * Allows application to override the creation of activities. This can be used to 112 * perform things such as dependency injection or class loader changes to these 113 * classes. 114 * <p> 115 * This method is only intended to provide a hook for instantiation. It does not provide 116 * earlier access to the Activity object. The returned object will not be initialized 117 * as a Context yet and should not be used to interact with other android APIs. 118 * 119 * @param cl The default classloader to use for instantiation. 120 * @param className The class to be instantiated. 121 * @param intent Intent creating the class. 122 */ 123 public @NonNull Activity instantiateActivityCompat(@NonNull ClassLoader cl, 124 @NonNull String className, @Nullable Intent intent) 125 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 126 try { 127 return (Activity) cl.loadClass(className).getDeclaredConstructor().newInstance(); 128 } catch (InvocationTargetException | NoSuchMethodException e) { 129 throw new RuntimeException("Couldn't call constructor", e); 130 } 131 } 132 133 /** 134 * Allows application to override the creation of receivers. This can be used to 135 * perform things such as dependency injection or class loader changes to these 136 * classes. 137 * 138 * @param cl The default classloader to use for instantiation. 139 * @param className The class to be instantiated. 140 * @param intent Intent creating the class. 141 */ 142 public @NonNull BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl, 143 @NonNull String className, @Nullable Intent intent) 144 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 145 try { 146 return (BroadcastReceiver) cl.loadClass(className).getDeclaredConstructor() 147 .newInstance(); 148 } catch (InvocationTargetException | NoSuchMethodException e) { 149 throw new RuntimeException("Couldn't call constructor", e); 150 } 151 } 152 153 /** 154 * Allows application to override the creation of services. This can be used to 155 * perform things such as dependency injection or class loader changes to these 156 * classes. 157 * <p> 158 * This method is only intended to provide a hook for instantiation. It does not provide 159 * earlier access to the Service object. The returned object will not be initialized 160 * as a Context yet and should not be used to interact with other android APIs. 161 * 162 * @param cl The default classloader to use for instantiation. 163 * @param className The class to be instantiated. 164 * @param intent Intent creating the class. 165 */ 166 public @NonNull Service instantiateServiceCompat(@NonNull ClassLoader cl, 167 @NonNull String className, @Nullable Intent intent) 168 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 169 try { 170 return (Service) cl.loadClass(className).getDeclaredConstructor().newInstance(); 171 } catch (InvocationTargetException | NoSuchMethodException e) { 172 throw new RuntimeException("Couldn't call constructor", e); 173 } 174 } 175 176 /** 177 * Allows application to override the creation of providers. This can be used to 178 * perform things such as dependency injection or class loader changes to these 179 * classes. 180 * <p> 181 * This method is only intended to provide a hook for instantiation. It does not provide 182 * earlier access to the ContentProvider object. The returned object will not be initialized 183 * with a Context yet and should not be used to interact with other android APIs. 184 * 185 * @param cl The default classloader to use for instantiation. 186 * @param className The class to be instantiated. 187 */ 188 public @NonNull ContentProvider instantiateProviderCompat(@NonNull ClassLoader cl, 189 @NonNull String className) 190 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 191 try { 192 return (ContentProvider) cl.loadClass(className).getDeclaredConstructor().newInstance(); 193 } catch (InvocationTargetException | NoSuchMethodException e) { 194 throw new RuntimeException("Couldn't call constructor", e); 195 } 196 } 197} 198