我的目标是将一个可变长度的字节数组从本机代码传递到Java端.Java类实例方法将bytearray作为其参数:
private void writeBuffer(final byte[] buffer)
{
}
Run Code Online (Sandbox Code Playgroud)
我能够在本机代码中找到方法ID:
jclass cls = (*env)->FindClass(env,"class_path");
jmethodID writeBufferMethodID = (*env)->GetMethodID(env, cls, "writeBuffer", "([B)V");
Run Code Online (Sandbox Code Playgroud)
但仍然无法弄清楚如何正确传递字节数组.我试过了:
jbyteArray retArray = (*env)->NewByteArray(env, data_size);
void *temp = (*env)->GetPrimitiveArrayCritical(env, (jarray)retArray, 0);
memcpy(temp, decoded_frame->data[0], data_size);
(*env)->CallVoidMethod(env, obj, writeBufferMethodID, retArray);
(*env)->ReleasePrimitiveArrayCritical(env, retArray, temp, 0);
Run Code Online (Sandbox Code Playgroud)
并且:
retArray = (*env)->NewByteArray(env, data_size);
(*env)->SetByteArrayRegion(env, retArray, 0, data_size, (jbyte *)decoded_frame->data[0]);
(*env)->CallVoidMethod(env, obj, writeBufferMethodID, retArray);
Run Code Online (Sandbox Code Playgroud)
调用Java方法,但一段时间后应用程序崩溃.此外,我收到的Java缓冲区中的所有值都等于零,因此看起来内容根本不会被复制.
我通过将它们写入二进制文件来验证本机端的缓冲区内容(decoding_frame-> data [0])并且没有问题,该文件包含我期望的内容.
我定期称这种方法; 数组的大小可以在每次调用中变化.
什么是正确和最有效的方法?在每次调用期间分配一个新数组显然是一个愚蠢的想法,但我不知道,如果数组大小不同,如何避免这种情况.
编辑:
我已经用这种方式重写了我的代码,现在似乎还可以.
在while循环中调用:
......做一些解码......
if(!retArray)
retArray = (*env)->NewByteArray(env, data_size); …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用本机共享库(.so),我通过调用加载它System.loadLibrary("xxx").它加载很好,我可以调用本机方法.
我想知道是否有可能检测应用程序使用哪个共享库.我试图通过PackageManager列出加载的库:
PackageManager pm = getPackageManager();
String applicationPackage = this.getApplicationInfo().packageName;
ApplicationInfo ai = pm.getApplicationInfo(applicationPackage, PackageManager.GET_SHARED_LIBRARY_FILES);
String[] soFiles = ai.sharedLibraryFiles;
Run Code Online (Sandbox Code Playgroud)
但它返回一个空列表.它仅适用于我的应用程序使用一些.jar库,例如com.google.android.maps,我uses-library在清单的应用程序标记中指定了这些库.
我怎样才能列出.so库?
我已经了解了ObjC中的块,语法清晰简单.我几乎可以在任何地方阅读"块是一个很棒的功能,语法是......".但是,我想念他们使用的真正优势.
也许这是一个愚蠢的问题 - 我刚开始使用ObjC,但是块的真正优势在于"传统"方法?谁能给我一些简短而明确的解释?
我为Android开发了一些原生库,并使用Boost库 - 只是基于头文件库.我面临的问题是,当我尝试将一些本机库与一些系统库链接时,UnsatisfiedLinkError会抛出它.这是由于NDK文档中所述的不同C++运行时:
您只能选择所有代码都依赖的单个C++运行时.不可能混合针对不同C++运行时编译的共享库.
系统库不使用RTTI和Exceptions,但我的库隐式使用它.我知道有宏BOOST_EXCEPTION_DISABLE和BOOST_NO_RTTI,但我不能让它工作.我试图将它们设置为编译器标志,并在config.hpp中,但没有运气 - 仍然有很多错误,如
cannot use typeid with -fno-rtti
Run Code Online (Sandbox Code Playgroud)
如何在Boost中禁用这些功能,甚至可能吗?
我将为Android OS创建一个共享库.虽然我已经在Eclipse中完成了一些Android应用程序,但我决定使用Visual Studio和vs-Android附加组件开始我的本机开发:
http://code.google.com/p/vs-android/
我非常熟悉VS和Google发现附加组件作为第一个结果之一.我已经完成了整个设置过程,安装了JDK,NDK,Ant,设置了系统变量,最后得到了一个工作项目.它就像一个魅力!但是有一个很大的缺点.我无法调试本机代码.
我知道有NDK-GDB工具,但在尝试设置时我经常失败.我已经阅读了NDK-GDB.html文档,丢弃了最初的vs-Android解决方案并成功完成了以下教程:
http://mhandroid.wordpress.com/2011/01/23/using-eclipse-for-android-cc-development/
但现在我在试图通过时再次陷入困境:
http://mhandroid.wordpress.com/2011/01/23/using-eclipse-for-android-cc-debugging/
http://mhandroid.wordpress.com/2011/01/23/using-cgdb-with-ndk-debug-and-cgdb-tutorial/
我也尝试过WinGDB - 刚刚导入的包含本机和Java代码的工作Eclipse项目,但它甚至都没有编译.
简而言之,这个难题有很多部分,但我仍然缺少其中一些.我担心我错过了使用像NDK-GDB这样的命令行工具调试代码的整个想法.
有人能为我提供一些解释和明确的步骤如何调试本机库(无论是vs-android还是Eclipse或其他什么都无关紧要)?请注意,我不是Linux大师,也不熟悉cygwin或gdbserver.
我创建了一个基于FFmpeg的电影播放器.它工作正常.解码速度非常快,在LG P970(带霓虹灯的Cortex A8)上,平均70 fps,640 x 424分辨率视频流,包括YUV2RGB转换.但是,存在一个瓶颈.它是在Canvas上绘制的.
我使用jnigraphics本机库将图片数据填充到本机侧的位图中,然后在SurfaceView中的Canvas上绘制这个位图.这是非常简单和常见的方法,但绘图需要44毫秒的位图,640 x 424分辨率,将fps降低到23并使这种技术无法使用......它需要比整个A/V帧解码更多!
有没有什么方法可以更快地绘制位图?我更喜欢使用OpenGLES 2在本机代码中完全呈现,但我读过它也可能很慢.所以现在怎么办?...
如何尽可能快地渲染位图?
我想用自定义视图(DISPLAY_SHOW_CUSTOM)创建选项卡式ActionBar(NAVIGATION_MODE_TABS).它应该是这样的:

我只需要能够通过顶行中的按钮浏览活动 - 正如我在正常 - 非选项卡模式下使用ActionBar一样,并且还能够在第二行中切换选项卡.如果我将ActionBar设置为选项卡式模式,自定义视图将消失,标签模式和自定义视图似乎是互斥的......它甚至可能吗?
没有ActionBar,有更多可行的方法可以做到这一点.通常我会创建一个带按钮的布局,将它包含在TabActivity中(现已弃用),就是这样.但我觉得这不是最好的解决方案,所以任何帮助或建议都表示赞赏.
提前致谢.
编辑:经过一番研究后,我发现它有效,它只是没有显示在我的4英寸屏幕上.但它仍然没有像我预期的那样工作.在更宽的屏幕上,自定义视图显示在选项卡的右侧 - 没关系,但在4英寸手机屏幕上根本不显示.
我认为最好的解决方案是使用ActionBarSherlock库(我不喜欢使用已弃用的功能,我的应用程序也必须在pre-sdk11版本的设备上工作)和片段 - 一个用于顶级ActionBar,另一个用于选项卡式视图.
我需要分发一个应用程序(播放器),该应用程序依赖于为给定ARM版本和扩展(Tegra,Neon)构建的本机库。这个本地库很大,因此我不能在一个通用包中分发所有版本。因此,我决定将应用程序分成一个小的通用.apk和更专业的.apks –无需任何活动的插件。
如何从主主机应用程序访问插件应用程序中的专用本机共享库?是否可以简单地使用
System.loadLibrary("path_to_library");
Run Code Online (Sandbox Code Playgroud)
如果是这样,我如何获得该库的路径?
在不可能的情况下如何解决这个问题?
我必须创建一个密钥分发服务器,它只是一个本地服务器,通过自己的API从DRM提供程序获取AES密钥,并将它们返回给连接的客户端.客户端是我自己的基于FFmpeg库的媒体播放器或本机Android媒体播放器.
我已经在Windows上使用Boost ASIO库和OpenSSL进行了实验 - 有一个如何创建简单HTTPS服务器和客户端的示例.在我的情况下,我必须只启用服务器访问专用的应用程序/客户端,所以我需要一个客户端身份验证.有一些事情我不清楚,因为我从来都不是这种东西的专家.
我知道HTTPS服务器必须要求客户端进行身份验证,客户端应该发送其证书,服务器然后reeds并验证证书中的一些数据.问题是:
我正在编写的所有内容都在本机级别执行,即它由Linux共享库实现.这就是为什么我认为对于普通的Android开发者而言,这对Linux专家来说是个问题.
有人可以解释我 - 在一些子弹中,如何做到这一点 - 如果有可能的话?任何提示也是受欢迎的!
非常感谢!
android ×6
android-ndk ×6
boost ×1
boost-asio ×1
c++ ×1
ffmpeg ×1
https ×1
java ×1
linux ×1
objective-c ×1
opengl-es ×1
openssl ×1