1 /*
2  * Copyright (C) 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 package com.android.launcher3.util;
17 
18 import android.content.Context;
19 import android.text.TextUtils;
20 import android.util.Log;
21 
22 import java.lang.reflect.InvocationTargetException;
23 
24 /**
25  * An interface to indicate that a class is dynamically loaded using resource overlay, hence its
26  * class name and constructor should be preserved by proguard
27  */
28 public interface ResourceBasedOverride {
29 
30     class Overrides {
31 
32         private static final String TAG = "Overrides";
33 
getObject( Class<T> clazz, Context context, int resId)34         public static <T extends ResourceBasedOverride> T getObject(
35                 Class<T> clazz, Context context, int resId) {
36             String className = context.getString(resId);
37             boolean isOverridden = !TextUtils.isEmpty(className);
38 
39             // First try to load the class with "Context" param
40             try {
41                 Class<?> cls = isOverridden ? Class.forName(className) : clazz;
42                 return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
43             } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
44                      | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
45                 if (isOverridden) {
46                     Log.e(TAG, "Bad overriden class", e);
47                 }
48             }
49 
50             // Load the base class with no parameter
51             try {
52                 return clazz.newInstance();
53             } catch (InstantiationException|IllegalAccessException e) {
54                 throw new RuntimeException(e);
55             }
56         }
57     }
58 }
59