android 使用反射获取MediaPlayer的Invoke方法
来源:互联网 发布:java string转boolean 编辑:程序博客网 时间:2024/06/06 06:35
最近有需求需要使用MediaPlayer的invoke接口去实现某些功能, 但是invoke接口是隐藏的, 没有在sdk中开放出来. 所以使用反射的方法来获取invoke接口, 但在实现的过程中出现一些问题, 在这里记录一下.
1.使用反射的方式获取隐藏的接口
if (mMediaPlayer != null) { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { request.writeInt(200); Class<?> cls = mMediaPlayer.getClass(); Method method = cls.getDeclaredMethod("invoke", Parcel.class, Parcel.class); method.setAccessible(true); //如果隐藏接口是public的, 这句可以不要 method.invoke(mMediaPlayer, request, reply); int result = reply.readInt(); if (0 == result) { return false; } else if (1 == result) { return true; } } catch (Exception e) { e.getCause().printStackTrace(); } finally { request.recycle(); reply.recycle(); } }
反射的调用步骤:
(1) 获取相关类的class
Class cls = mMediaPlayer.getClass();
或者通过包名获取:
Class cls = Class.forName (“android.media.MediaPlayer”);
(2) 通过方法名获得方法接口, 如果方法有参数, 需要将参数的class传入
Method method = cls.getDeclaredMethod(“invoke”, Parcel.class, Parcel.class);
(3) 通过Method的invoke接口来实现方法的调用, 这时候需要传参, 将参数传入:
method.invoke(mMediaPlayer, request, reply);
2.出现的问题
当通过这种方式调用后会发现无效, 并且会打印下面的error信息:
01-01 08:31:42.270 W/System.err( 1475): java.lang.reflect.InvocationTargetException01-01 08:31:42.270 W/System.err( 1475): at java.lang.reflect.Method.invokeNative(Native Method)01-01 08:31:42.270 W/System.err( 1475): at java.lang.reflect.Method.invoke(Method.java:511)
这个问题搞了好久, 反射调用的方法应该没什么问题, 错误应该是其他的, 仔细看log发现有下列信息:
01-01 08:31:42.269 E/Parcel ( 3212): Reading a NULL string not supported here.
我没有传入任何string下去, 却报出这个error, 应该是需要再出入一个string下去.
这个时候查看MediaPlayer的源码, 看到selectOrDeselectTrack等方法内部也是调用的invoke接口:
private void selectOrDeselectTrack(int index, boolean select) throws IllegalStateException { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(select ? INVOKE_ID_SELECT_TRACK : INVOKE_ID_DESELECT_TRACK); request.writeInt(index); invoke(request, reply); } finally { request.recycle(); reply.recycle(); } }
这里面与我写的调用invoke接口多了一句:
request.writeInterfaceToken(IMEDIA_PLAYER);
IMEDIA_PLAYER的值为:
private final static String IMEDIA_PLAYER = "android.media.IMediaPlayer";
当我将这句加上测试后, 果然没问题了, 调用成功. 这句代码的意思是标识远程服务的名称. 不然不知道去启动哪个服务来操作.
其实MediaPlayer中有提供方法来获取Parcel对象, 但是此方法也是隐藏的:
public Parcel newRequest() { Parcel parcel = Parcel.obtain(); parcel.writeInterfaceToken(IMEDIA_PLAYER); return parcel; }
这个方法的内部也是调用了writeInterfaceToken接口.
3.其他
如果可以查看源码, 其实每个方法的使用源码中都有对应的test例子, 例如现在说的invoke方法, 在源码中有 MediaPlayerInvokeTest.java, 这里面介绍了如何使用invoke接口, 下面是这个类的内容:
// Tests for the invoke method in the MediaPlayer. public class MediaPlayerInvokeTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { private static final String TAG = "MediaPlayerInvokeTest"; private MediaPlayer mPlayer; private Random rnd; public MediaPlayerInvokeTest() { super("com.android.mediaframeworktest", MediaFrameworkTest.class); rnd = new Random(Calendar.getInstance().getTimeInMillis()); } @Override protected void setUp() throws Exception { super.setUp(); mPlayer = new MediaPlayer(); } @Override protected void tearDown() throws Exception { mPlayer.release(); super.tearDown(); } // Generate a random number, sends it to the ping test player. @Suppress @MediumTest public void testPing() throws Exception { mPlayer.setDataSource("test:invoke_mock_media_player.so?url=ping"); Parcel request = mPlayer.newRequest(); Parcel reply = Parcel.obtain(); int val = rnd.nextInt(); request.writeInt(val); mPlayer.invoke(request, reply); assertEquals(val, reply.readInt()); } }
这次的收获就是要学会善于查看android源码.
- android 使用反射获取MediaPlayer的Invoke方法
- java invoke 反射方法的使用详解
- Java 反射 ,Method的invoke()方法的使用
- 反射机制--方法的反射m.invoke()
- 通过Invoke反射类的private方法
- java中的反射--method的invoke方法
- MediaPlayer获取实例的方法
- Android Mediaplayer的使用
- android的mediaPlayer使用
- 反射invoke()方法
- 反射之invoke方法
- java invoke 反射机制的使用
- 使用java反射中的getMethod,invoke方法调用对象方法的实例
- java 反射 invoke使用
- java反射Method中的如何调用任意方法,即invoke()的使用
- java反射之Method类中invoke()方法的使用
- Android中MediaPlayer的setDataSource方法的使用
- 1.Android MediaPlayer的使用
- 轻松搞定面试中的二叉树题目
- 2015-2016 ACM-ICPC, NEERC, Moscow Subregional Contest K
- 35. Search Insert Position
- leetcode Repeated DNA Sequence
- JS setInterval setTimeout的用法
- android 使用反射获取MediaPlayer的Invoke方法
- 设计模式(八)——策略模式
- SQL Server服务器I/O问题的初步诊断
- 用两个栈来实现一个队列()
- jQuery Mobile 滑动显示面板
- Web分页实现及实例演示(一)——subList()
- Xcode_7 iOS_9 模态视图 Objective-C (15)
- 初识html5之基本html结构
- (6)HTML5-引用CSS