Java中使用反射机制操作硬件

使用使用"mmm frameworks/base/"命令编译 frameworks/base/core/java/android/os/ ILedService.aidl文件,在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/目录下会生成ILedService.java文件,内容如下:
/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/./core/java/android/os/ILedService.aidl
 */
package android.os;
/** {@hide} */
public interface ILedService extends android.os.IInterface
{
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements android.os.ILedService
	{
		private static final java.lang.String DESCRIPTOR = "android.os.ILedService";
		/** Construct the stub at attach it to the interface. */
		public Stub()
		{
			this.attachInterface(this, DESCRIPTOR);
		}
		/**
		 * Cast an IBinder object into an android.os.ILedService interface,
		 * generating a proxy if needed.
		 */
		public static android.os.ILedService asInterface(android.os.IBinder obj)
		{
			if ((obj==null)) {
				return null;
			}
			android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
			if (((iin!=null)&&(iin instanceof android.os.ILedService))) {
				return ((android.os.ILedService)iin);
			}
			return new android.os.ILedService.Stub.Proxy(obj);
		}
		@Override public android.os.IBinder asBinder()
		{
			return this;
		}
		@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
		{
			switch (code)
			{
				case INTERFACE_TRANSACTION:
				{
					reply.writeString(DESCRIPTOR);
					return true;
				}
				case TRANSACTION_ledCtrl:
				{
					data.enforceInterface(DESCRIPTOR);
					int _arg0;
					_arg0 = data.readInt();
					int _arg1;
					_arg1 = data.readInt();
					int _result = this.ledCtrl(_arg0, _arg1);
					reply.writeNoException();
					reply.writeInt(_result);
					return true;
				}
			}
			return super.onTransact(code, data, reply, flags);
		}
		private static class Proxy implements android.os.ILedService
		{
			private android.os.IBinder mRemote;
			Proxy(android.os.IBinder remote)
			{
				mRemote = remote;
			}
			@Override public android.os.IBinder asBinder()
			{
				return mRemote;
			}
			public java.lang.String getInterfaceDescriptor()
			{
				return DESCRIPTOR;
			}
			@Override public int ledCtrl(int which, int status) throws android.os.RemoteException
			{
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				int _result;
				try {
					_data.writeInterfaceToken(DESCRIPTOR);
					_data.writeInt(which);
					_data.writeInt(status);
					mRemote.transact(Stub.TRANSACTION_ledCtrl, _data, _reply, 0);
					_reply.readException();
					_result = _reply.readInt();
				}
				finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}
		}
		static final int TRANSACTION_ledCtrl = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
	}
	public int ledCtrl(int which, int status) throws android.os.RemoteException;
}
在前面生成apk的文章中,通过 iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));来获得一个ILedService对象,之后就可以通过这个对象的ledCtrl方法来操作LED。本文中,使用java的反射机制来生成apk,MainActivity.java源码如下:
package mobiletek.ledreflect;

import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import android.os.IBinder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MainActivity extends AppCompatActivity {
    private boolean ledon = false;
    private Button button = null;

    Object proxy = null;
    Method ledCtrl = null;

    private CheckBox checkBoxLed1 = null;
    private CheckBox checkBoxLed2 = null;
    private CheckBox checkBoxLed3 = null;
    private CheckBox checkBoxLed4 = null;

    int []ledctrl = {0x12, 0x34, 0x56, 0x78};

    class MyButtonListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            ledon = !ledon;
            if (ledon) {
                button.setText("ALL OFF");
                checkBoxLed1.setChecked(true);
                checkBoxLed2.setChecked(true);
                checkBoxLed3.setChecked(true);
                checkBoxLed4.setChecked(true);

                try {
                    for (int i = 0; i < 4; i++)
                        ledCtrl.invoke(proxy, ledctrl[i], 1);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
            else {
                button.setText("ALL ON");
                checkBoxLed1.setChecked(false);
                checkBoxLed2.setChecked(false);
                checkBoxLed3.setChecked(false);
                checkBoxLed4.setChecked(false);

                try {
                    for (int i = 0; i < 4; i++)
                        ledCtrl.invoke(proxy, ledctrl[i], 0);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void onCheckboxClicked(View view) {
        // Is the view now checked?
        boolean checked = ((CheckBox) view).isChecked();

        // Check which checkbox was clicked
        try {
            switch(view.getId()) {
                case R.id.LED1:
                    if (checked) {
                        Toast.makeText(getApplicationContext(), "LED1 on", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[0], 1);
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "LED1 off", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[0], 0);
                    }
                    break;
                case R.id.LED2:
                    if (checked) {
                        Toast.makeText(getApplicationContext(), "LED2 on", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[1], 1);
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "LED2 off", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[1], 0);
                    }
                    break;

                case R.id.LED3:
                    if (checked) {
                        Toast.makeText(getApplicationContext(), "LED3 on", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[2], 1);
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "LED3 off", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[2], 0);
                    }
                    break;

                case R.id.LED4:
                    if (checked) {
                        Toast.makeText(getApplicationContext(), "LED4 on", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[3], 1);
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "LED4 off", Toast.LENGTH_SHORT).show();
                        ledCtrl.invoke(proxy, ledctrl[3], 0);
                    }
                    break;
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button)findViewById(R.id.BUTTON);
        try {
            Method getService = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            Object ledService = getService.invoke(null, "led");
            Method asInterface = Class.forName("android.os.ILedService$Stub").getMethod("asInterface", IBinder.class);
            proxy = asInterface.invoke(null, ledService);
            ledCtrl = Class.forName("android.os.ILedService$Stub$Proxy").getMethod("ledCtrl", int.class, int.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        checkBoxLed1 = (CheckBox) findViewById(R.id.LED1);
        checkBoxLed2 = (CheckBox) findViewById(R.id.LED2);
        checkBoxLed3 = (CheckBox) findViewById(R.id.LED3);
        checkBoxLed4 = (CheckBox) findViewById(R.id.LED4);

        button.setOnClickListener(new MyButtonListener());
    }
}
在onCreate方法中,首先通过下面两行代码将 ILedService.Stub.asInterface(ServiceManager.getService("led"));实参替换掉:
Method getService = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
Object ledService = getService.invoke(null, "led");
ServiceManager.getService("led")被替换为ledService, ServiceManager的getService方法在frameworks/base/core/java/android/os/ServiceManager.java文件中定义:
public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
}
通过proxy = asInterface.invoke(null, ledService);返回IBinder对象,再向上转换为Object对象。接下来通过下面两行,调用ILedService接口的内部类Stub的asInterface方法获得ILedService对象proxy,再向上转换为Object对象:
Method asInterface = Class.forName("android.os.ILedService$Stub").getMethod("asInterface", IBinder.class);
proxy = asInterface.invoke(null, ledService);
最后通过ledCtrl = Class.forName("android.os.ILedService$Stub$Proxy").getMethod("ledCtrl", int.class, int.class);获得 ILedService接口的内部类Stub的内部类Proxy的ledCtrl方法,之后就可以通过ledCtrl.invoke来操作LED,由于ledCtrl方法没有用static声明,所以调用时需要传入一个实例化对象,例如:ledCtrl.invoke(proxy, ledctrl[0], 1);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值