Fork me on GitHub

采访Philipp Crocoll:安卓平台上整合Java和C#

在这个采访中,我们跟开源开发者Philipp Crocoll讨论了关于Keepass2Android的相关话题。Keepass2Android不仅具有强大的密码存储的功能,还是在一个单独的安卓应用同时使用Java和C#的很好的案例。

InfoQ:能否介绍一下Keepass2Android设计初衷是为了解决什么问题?

Keepass 2是一个强大的密码管理器,我已经使用了很长一段时间。它有一些很好的插件,比如可以集成到Chrome或者Firefox浏览器中的那些插件。我在手机上也使用Keepassdroid进行密码访问。不幸的是,它现在只能实现数据库的读访问(最初的Keepass 1还提供了写的功能,但对我却没多大帮助)。随着使用手机的频率越来越高,我就想要创建一个账户,来存储手机上的这些密码了。

于是,我开始思考自己去添加这些功能,我决定用Mono安卓版将这个应用移植为C#版,并且基于Keepass 2的源代码来实现密码数据库的修改功能。

InfoQ:Keepass2Android跟其他的密码管理器有什么不同?

当我的应用差不多快写完的时候,Keepassdroid还加入了写支持的功能(至少已经处于Beta模式了)。我决定无论如何都要发布它,因为它已经有了一些新特性——包括完全兼容Keepass 2、浏览器集成以及QuickUnlock等。QuickUnlock是一种内存数据库技术(即从不在SD卡上存储主密码)。为了能够在用户丢失手机时保护用户数据库的安全,必须输入一个短密码才能解锁数据库。这比每次都要输出强安全的、过长的主密码要好得多。

自最初的版本以来,我已经添加了大量的新功能:用户可以使用键盘输入验证码(因为安卓中的剪贴板是不安全的);对PC版的用户而言,可以选择通过WebDAV、FTP、 SFTP、 Dropbox、OneDrive 或者GoogleDrive等进行数据库同步。还有一些更多的“专家”功能,比如使用一次性密码 (通过NFC用Yubikey NEO输入,https://www.yubico.com/products/yubikey-hardware/yubikey-neo/)或对Keepass 2占位符体系的支持(http://keepass.info/help/base/placeholders.html)

一方面,我尽力让没有太多使用经验的人也能够使用这个应用,同时,也希望为担心安全问题的用户提供选择。

InfoQ:在Keepass2Android中使用C#代替Java,你选择了什么语言?

写加密的文件必须非常小心:如果你写错了一点,文件就可能成为无用的或者不可读取的。用户必须确信他们的密码数据库是完整无缺的!为了确保不会损坏任何数据库,我决定基于Keepass 2的最初实现。由于Keepass 2是用C#写的,我评估了在安卓上用此实现的可能性。这是我第一次接触Xamarin的安卓版Mono。我早期的工作中曾经做过一些C#开发,也有过一点安卓开发经验。将这两个东西放到一起似乎是一件很有趣的事情。我本人对新知识非常渴望,因此,这对我而言是一个很棒的选择。事实证明,安卓版Mono是一个很好的平台:你可以同时拥有.net框架以及Java平台和安卓类库的强大威力。

另一个好处是,可以直接将Java库包含进来。事实上,我利用Eclipse对安卓更好的支持用Java完成了应用的一部分编写(云存储、自定义键盘)。

InfoQ:将Java和C #代码整合到同一个应用中主要需要做哪些事情?这很顺利吗?还是遇到了一些重大的挑战?

Xamarin团队已经围绕两种语言的融合做了很多工作,包括在.net项目中创建一个绑定库,使得Java库可以被引用。这会生产一些C#类和接口,这些接口可以用于调用Java代码。这些工作完美无暇,甚至可以自动转换常见的命名规则和模式。举一个简单的例子:“String getPackageName()”会转换成“string PackageName { get {……} }”。而事件的处理:“setOnClickListener(...)”会自动转换成C#中的“Click += ……”。

对于一些简单的接口,我还没有发现任何问题。如果你想要绑定一些复杂的库,通常需要按以下网页中的描述手工做些工作:

http://docs.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding_a_java_library_(.jar)/api_metadata_reference/

随着Java类绑定以及与C#的对接,用起来感觉就跟用C#库差不多。我所看到的极少的不同是,从Java.Lang.Object中派生出一个类时,需要添加这样一行代码:

catch (Java.Lang.Exception e)

这行代码是非常必要的,因为当实现一个起初在Java定义的接口时,需要将这个类的对象回传给Java代码。

在我实现的代码中,这是唯一一处“对象”处于两台虚拟机的地方,这两个世界都有着各自的垃圾收集机制。

InfoQ:你会考虑针对未来的安卓项目再次使用C#吗?

我认为安卓版Mono是我的工具集中的一个工具。尽管它很强大,但是它不是必需的,或者说它不一定适合所有的项目。

在Keepass2Android中使用C#的原因是,它让我能够在一个安卓App中用到一个非常强大的库(Keepass 2 code)。并且,对于每一个有C#背景的朋友而言,使用C#的一些好的特性(LINQ、Lambdas、动态类型等等) 以及.net框架,也是非常不错的。

另一个原因,是安卓版Mono的可移植性,借助它,代码可以运行在Android、iOS(它们使用Xamarin)上,当然还可以运行在Windows和Linux(使用Mono) 上。但不幸的是,它也有一个缺点——Mono库添加了一些MB级大小的应用包(不同的框架具体大小也有所不同),导致构建过程相比纯Java要慢很多。

目前,我的App从Visual Studio上发布需要2分多钟的时间。为了缓解这个问题,我为那些应用功能少、构建时间快的开发者添加了构建选项,此外,我还尝试在外部项目中开发一些新的特性。

还有一点,IDE对于一些安卓特定功能的支持比不上Eclipse或者是Android Studio,这会减慢开发的速度。

出于这些原因,我可能会根据具体的项目来决定是不是要使用Mono安卓版。

Keepass2Android可以在CodePlex中获取,GPLv3 license

查看英文原文:Interview with Philipp Crocoll on Java/C# Integration for Android

中文原文:http://www.infoq.com/cn/news/2014/06/Keepass2Android

posted @ 2014-06-07 22:08 张善友 阅读(...) 评论(...) 编辑 收藏