关于Android 控件没有动态设置界面效果时,如何处理
关于Android 控件没有动态设置界面效果时,如何处理
例子:android:scrollbarThumbVertical 动态设置 -->listView
如果控件只有静态xml界面的设置,没有动态设置时,需要去查看安卓控件的源码,看该控件继承了那个父控件的方法,然后利用反射调用!
不同的Android 版本,源码可能不同!
Android 11.0
View.java
/**
* Defines the vertical scrollbar thumb drawable
* @attr ref android.R.styleable#View_scrollbarThumbVertical
*
* @see #awakenScrollBars(int)
* @see #isVerticalScrollBarEnabled()
* @see #setVerticalScrollBarEnabled(boolean)
*/
public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
initializeScrollBarDrawable();
mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
}
<ListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="250dp"
android:entries="@array/array_adapter_strs" />
//ListView 动态改变scrollbarThumbVertical
private void changeViewProgress(){
try {
Class three = Class.forName("android.view.View");
Method method_2 = three.getMethod("setVerticalScrollbarThumbDrawable", Drawable.class);
method_2.invoke(listView,getDrawable(R.drawable.title_music));
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
java反射调用Android系统服务
Android 源码里的一些反射应用
+ //add text
+ private void setProperty(String key, String value){
+ try {
+ Class<?> c = Class.forName("android.os.SystemProperties");
+ Method method = c.getMethod("set",String.class,String.class);
+ method.invoke(c,key,value);
+ }catch (Exception e){
+ Log.d(TAG,"xxxxxxxxxx");
+ }
+ }
+ //add text
public static String getSystemProperty(String property, String defaultValue) {
try {
Class clazz = Class.forName("android.os.SystemProperties");
Method getter = clazz.getDeclaredMethod("get", String.class);
String value = (String) getter.invoke(null, property);
if (!TextUtils.isEmpty(value)) {
return value;
}
} catch (Exception e) {
Log.d(TAG, "Unable to read system properties");
}
return defaultValue;
}
如何反射系统服务类的函数?
PowerManager类并没有提供关机的shutdown接口,而是通过IBinder这种Android中特有的通信模式,与PowerManagerService 类进行通信.
PowerManagerService是PowerManager 类中定义的接口的具体实现,并进一步调用Power 类来与下一层进行通信.
在PowerManagerService实现了shutdown接口,power服务实现了关机功能.
PowerManager的实现通过IPowerManager来调用Power服务的接口,
IPowerManager是AIDL文件自动生成的类,便于远程通信.
IPowerManage.aidl文件目录:framework/base/core/java/android/os/IPowerManage.aidl
IPowerManager实现了shutdown接口.所以,如果我们能够获得Power服务的IBinder,通过反射调用shutdown方法就能实现关机功能.
需要注意的是,ServiceManager管理着系统的服务程序,它保存着所有服务的IBinder,通过服务名就能获取到这个服务的IBinder.
但ServiceManager这个类也是HIDE的,也需要反射进行调用两次.
通过两次反射调用,就能调用power服务实现的关机功能.
实际使用需要:android:sharedUserId="android.uid.system" ,系统app和权限
//关机
try {
//获得ServiceManager类
Class<?> ServiceManager = Class.forName("android.os.ServiceManager");
//获得ServiceManager的getService方法
Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
//调用getService获取RemoteService
Object oRemoteService = getService.invoke(null,Context.POWER_SERVICE);
//获得IPowerManager.Stub类
Class<?> cStub = Class.forName("android.os.IPowerManager$Stub");
//获得asInterface方法
Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
//调用asInterface方法获取IPowerManager对象
Object oIPowerManager = asInterface.invoke(null, oRemoteService);
//获得shutdown()方法
Method shutdown = oIPowerManager.getClass().getMethod("shutdown",boolean.class,boolean.class);
//调用shutdown()方法
shutdown.invoke(oIPowerManager,false,true);
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
//U盘挂载
public static void mountDisk() {
Log.v(TAG, "mountDisk begin");
try {
Class<?> clz = Class.forName("android.os.ServiceManager");
Method getService = clz.getMethod("getService", String.class);
Object powerService = getService.invoke(null, "mount");
Class<?> cStub = Class.forName("android.os.storage.IStorageManager$Stub");
Method asInterface = cStub.getMethod("asInterface", IBinder.class);
Object IPowerManager = asInterface.invoke(null, powerService);
Method shutDown = IPowerManager.getClass().getMethod("mount", String.class);
shutDown.invoke(IPowerManager, "public:8,1");
} catch (Exception e) {
e.printStackTrace();
}
Log.v(TAG, "mountDisk end");
}
public static void unmountDisk() {
Log.v(TAG, "unmountDisk begin");
try {
Class<?> clz = Class.forName("android.os.ServiceManager");
Method getService = clz.getMethod("getService", String.class);
Object powerService = getService.invoke(null, "mount");
Class<?> cStub = Class.forName("android.os.storage.IStorageManager$Stub");
Method asInterface = cStub.getMethod("asInterface", IBinder.class);
Object IPowerManager = asInterface.invoke(null, powerService);
Method shutDown = IPowerManager.getClass().getMethod("unmount", String.class);
shutDown.invoke(IPowerManager, "public:8,1");
} catch (Exception e) {
e.printStackTrace();
}
Log.v(TAG, "unmountDisk end");
}
public static boolean isUsbDiskMounted() {
String mount = SystemPropertiesUtil.getProperty("vold.usbdisk.state", "");
return "mounted".equals(mount);
}
系统测试,不反射使用
IPowerManager mPowerManager;
PowerManager mPm;
PowerManager.WakeLock mProx;
protected Test[] tests() {
mPowerManager = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
mPm = (PowerManager)getSystemService("power");
mProx = mPm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "PowerTest-prox");
return mTests;
}
工具类
/**
* 反射工具
*
* @author GaoFei
*/
public class ReflectUtils {
private static final String TAG = "ReflectUtils";
public static void setFieldValue(Object targetObject, String filedName, Object filedvalue) {
try {
Field field = targetObject.getClass().getDeclaredField(filedName);
field.setAccessible(true);
field.set(targetObject, filedvalue);
} catch (Exception e) {
Log.e(TAG, "setFieldValue->filedName:" + filedName);
Log.e(TAG, "setFieldValue->value:" + filedvalue);
Log.e(TAG, "setFieldValue->exception:" + e);
}
}
public static Object getFieldValue(Object targetObject, String filedName) {
try {
Field field = targetObject.getClass().getDeclaredField(filedName);
field.setAccessible(true);
return field.get(targetObject);
} catch (Exception e) {
Log.e(TAG, "getFieldValue->filedName:" + filedName);
Log.e(TAG, "getFieldValue->exception:" + e);
}
return null;
}
public static Object invokeMethod(Object object, String methodName, Class<?>[] paramTypes, Object[] values) {
try {
Method method = object.getClass().getDeclaredMethod(methodName, paramTypes);
method.setAccessible(true);
return method.invoke(object, values);
//return method.invoke(object, paramTypes);
} catch (Exception e) {
Log.e(TAG, "invokeMethod->methodName:" + methodName);
Log.e(TAG, "invokeMethod->exception:" + e);
}
return null;
}
public static Object invokeMethodNoParameter(Object object, String methodName) {
try {
Method method = object.getClass().getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(object);
//return method.invoke(object, paramTypes);
} catch (Exception e) {
Log.e(TAG, "invokeMethod->methodName:" + methodName);
Log.e(TAG, "invokeMethod->exception:" + e);
}
return null;
}
./packages/apps/Settings/src/com/android/settings/display/DrmDisplaySetting.java
public static String[] getConnectorInfo() {
Object rkDisplayOutputManager = null;
try {
rkDisplayOutputManager = Class.forName("android.os.RkDisplayOutputManager").newInstance();
} catch (Exception e) {
// no handle
}
if (rkDisplayOutputManager != null) {
return (String[]) ReflectUtils.invokeMethodNoParameter(rkDisplayOutputManager, "getConnectorInfo");
}
return null;
}
反射的基本概念
SettingLib
无法直接使用系统隐藏类、变量、接口导致的编译错误的 解决经验
android FrameWork 定制 绕开系统权限管控
开发解决Accessing hidden method限制
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!