月度归档:2011年01月

QQ+Discuz! = ?

记得去年 8 月份看到的新闻–“腾讯终于全面收购 Discuz!”,在收购完成之后一直没有看到 Tencent 方面有什么大的动作。不过就在前几日上某论坛下载东西的时候发现已经可以通过 QQ 号来登录论坛了。

image

我想大部分的人都曾有过这样的经历,从 Google 或者百度搜索到某个资源,该资源就是某论坛的某个帖子的附件,要下载的话至少是需要登录用户才可能下载,当然更有甚者还需要回复或者等级达到一定程度。这些论坛中的种种限制姑且不论,不过对于没有账号的用户那么其注册的过程是必不可少的,用户在不断的找寻资源的过程中会在形形色色的各种论坛注册过账号,当然可能很多账号只会使用一次,仅仅是为了下载当时非常需要的那个资源而已。然而注册的流程总是耗时的,而且很多余,到了一定时间,用户到了某个论坛时,都会先试试自己常用的账号是否可能登录,因为他自己根本无法确定自己是否注册过该论坛的账号。

那么使用 QQ 号呢,我想如今 QQ 号已经能成为众多企业的直接营销和客服 IM 工具,更别说个人对 QQ 号的依赖了,某个人丢失了 QQ 号就意味着他将会失去大半在网络上的人际网络,也就是说如今的 QQ 号对于网民来说,类似于如今的 PC 内存都普遍在 128M 以上了。使用 QQ 号直接打通所有论坛登录第一步,绝对只是一个开始。这可能只是 Tencent 布局的开头,从我个人臆想的角度来看,可能会有一些这样的发展:

  1. 使用 QQ+Discuz! 打造一个中国式的”CloseID”与 Google 等牵头的”OpenID”形成一种比较可爱的局势,这个在我国绝对不是不可能。
  2. QQ 用户的 Avatar 以及各种 VIP 服务是否可以延伸到 Discuz! 中来,也就是利用 QQ 的 Avatar 可以形成一个中国式的 ”Gravatar”,解决众多论坛注册之后第一步上传头像这么通用而又繁琐的步骤,利用 QQ 秀已有的积累和出色的设计完全可以吸引到不少的用户。
  3. QQ 用户的诸多 VIP 服务是否可以与论坛互通,例如通过分成等手段,借助 Q 币这个成熟灵活的支付手段,为论坛高级服务提供支付支持,在论坛之后发展的过程中,这个并不是不可能。特别是从国外 Quora 近来火爆异常的现象来看, 论坛的垂直化和专业化是未来的趋势, 更多的论坛可能必须走精品路线, 可能以知识消费为主的一些论坛会成为主流,那么消费产生的支付,可以由 Tencent 来协助站长和用户完成,不需要自行开发和维护这摊子事情。

目前臆测到的内容大概就是这些,不过从长远看来,如果腾讯出手来做这些事情,并不是没有可能做好的,毕竟用户全中国最多的 IM 用户和论坛用户,实在是不可小觑,而这两拨用户的高度重合更是为其业务的深度挖掘和整合提供了一个非常非常好的切入口,也许将来的某天,我们真的可以看到在本土的应用中,QQ 成为了一个基础服务的提供者,而不再是只会在 Windows 右下方频繁弹窗的 IM 软件了。

===============================分割线====================================

我非常非常喜欢 QQ 这款软件,即便我常年都是光着身子跟人聊天,即便是它有不少的广告,即便是它偶尔会弹窗,但是它真的能帮我解决问题,首先聊天不是问题,视频,群通话,远程协助,文件传输,每一个功能我想都是在同类软件中的佼佼者。虽然在 Ubuntu 下不能体验到 PC 上 QQ 客户端那么丰富的功能,不过 WebQQ 是一个不错的替代者,体验依然可以算是上佳之作了。对于腾讯常年不创新不断复制的言论,我想我不必说什么,在同类产品中如果能找到腾讯的产品,我往往会选择腾讯的,因为设计感相对其他产品会好很多,当然安全类产品我想我是不会选用任何一家国内的产品的,其中包括了没事就帮我们查木马的腾讯的安全产品。

近期 Android 开发经验积累

Android 中实现动态更改控件尺寸

android 中编写控件,通常我们采用 XML 格式的 Layout 文件来进行描述控件的大小和位置。当时某些时候我们还是很有必要在程序运行时更改控件的大小。

例如某些时刻程序执行时,控件关联数据发生改变可能导致控件对数据的呈现不能达到最佳,例如有两个 ListView 在当前窗体中,ListViewAListViewB 分别对应两组数据,一组数据对应本月代码提交列表,另一组对应本月 Bug 修复列表。当两组数据相当之时 ( 即数量相差无几 ),保持两个控件高度一致,可能两个 ListView 都会出现滚动条或者均不出现滚动条。但是当本月代码提交列表条目数远远超出本月 Bug 修复列表时 ( 本月主要任务是新接口的设计和功能开发,其中包含 Bug 的开发,-_-!)。如果依然保持两个控件高度一致的话,那么显然对于用户来说是不友好的,此时用户的视觉焦点应该更多的是在代码提交列表,所以可以适当地增大代码提交列表的高度而减小 Bug 列表的高度。更有可能的设计中就存在选择某个视图的功能,例如切换到 Bug 列表视图时,需要将 Bug 列表高度扩展到全屏幕高度等等。

其实主要代码就几行,例如程序中是通过某个响应某个控件的某个事件来完成列表高度改变,例如通过单击某个按钮来改变某个列表的高度:

布局文件如下:

<?xml version=“1.0” encoding=“utf-8”?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:orientation=“vertical” android:layout_width=“fill_parent”

android:layout_height=“fill_parent”>

<Button android:id=“@+id/change_view_size”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“ChangeSize” android:onClick=“onViewClick” />

<ImageView android:id=“@+id/logo” android:layout_width=“wrap_content”

android:layout_height=“wrap_content” android:src=“@drawable/logo”/>

<ListView android:id=“@+id/network_infos”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content” />

<ListView android:id=“@+id/network_infos2”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content” />

</LinearLayout>

关键代码如下:

public void onViewClick(View view){

// 单击 ChangeSize按钮,改变列表高度

if(view == mChangeViewSize){

mNetInfoList.post(new Runnable() {

@Override

public void run() {

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, mNetInfoList.getHeight()/2);

mNetInfoList.setLayoutParams(params);

mNetInfoList.requestLayout();

}

});

}

}

使用线程避免出现 ANR 异常

Android 中经常会出现 ANR 错误,因为经常性的 Android 桌面也会出现该问题,该问题主要是因为当前程序在 5 秒中内未能完成 UI 事件的响应,Android 认为该程序已经进入了无响应状态,Android 主动弹出一个提示框,提示用户是继续等待该程序还是将其强制关闭。

我们来看看 Google I/O 大会上的一个 PPT 中的分享:

ANRs (“Application Not Responding”)

ANRs happen when,

main thread (“event thread” / “UI thread”) doesn’t respond to

input event in 5 seconds,

a BroadcastReceiver doesn’t finish in 10 seconds

typically, when

doing network operations on main thread,

doing slow ‘disk’ operations (un-optimized SQL) on the main thread

那么防止这些问题的出现,很多时候都是需要使用线程来进行的,特别是连网的操作通常都是耗时的,而且极有可能出现连接超时的错误 ( 国内的网络环境,你懂的 )

还有就是某些有 left join right join 等的 SQL 查询也是有可能导致耗时过长的,可以尝试着使用 AsyncQueryHandler类来实现异步查询。

另外一定要注意在 BroadcastReceiver 中的 onReceive(Context context, Intent intent) 方法中的操作时间不能超过 10s,否则也可能出现 ANR 异常,那么如果觉得有可能触碰到临界值时还是选择使用线程吧

PS: 之前一直以为 Service 是在自身独有的线程中执行的,直到最近才明白,其实并不是这样的。我们来看看官方的说明:

A Service is an application component representing either an application’s desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.

但是接下来的说明才是最重要的:

Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Application Fundamentals: Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.

这也就是说 Service 通常都是在主线程中执行的,也就是说我们通常在 ServiceonCreate()onStart(Intent intent, int startId) 方法中执行的操作如果耗时耗资源,那么就应该另起线程,或者选择 IntentService 来实现,因为 IntentService 拥有自己独有的线程来执行其操作。所以还是建议使用 Service 时一定要注意。

不要在线程内部使用 TOAST

android 中,我们通常会使用 Toast 来通知用户一些信息,例如网络出现异常等等,但是经过实践表明在线程中使用 Toastshow() 方法似乎是不可行的,因为 Toast 最终的所有显示操作应该都是处于 UI 主线程中,如果我们在子线程中做这样的操作,显然是违背了“只在主线程中刷新 UI” 的原则,不过由于 Toast 的特殊性,其抛出的异常跟在子线程中改变 View 控件的异常并不一致,其抛出的异常是你需要在使用 handler 之前通过 Looper.prepare() 方法来将当前线程作为一个 looper,这显然是不对的。所以在线程中需要作任何 UI 操作,还是需要通过 handler 来通知主线程进行操作。

也扯 Android 开发

首先声明一下,我做移动平台开发的时间很短,短到还不足一年,其次再强调一下,我涉及的移动开发平台只是 Android。这就意味着我看到的东西非常非常的片面,甚至都没有参考价值和意义。只是自己周末觉得应该写个博客,而暂时也没有整理好的技术博客,所以索性就扯一下。

在做 Android 之前,我做过一年时间的 JNI 开发,一门原本非常非常偏门的中间件开发技术,在进入之前的公司 (SuperMap) 之前,我从未接触过 JNI 开发,虽然在零星地做着一些 Java 方面的工作,但是均只限于 Demo 的学习与演练,绝对没有半分实践的经验。进入超图之后,开始学习 JNI 开发技术,半年之后渐入佳境,日常的开发工作之余开始接触一些业务的东西,也就是说开始接触了一些技术支持方面的工作,偶尔需要到客户的现场处理缺陷或者针对用户的使用场景提出解决方案。当然这么说好像有点大,好吧,我承认有点虚。不过当时山中无老虎,猴子尚且称霸王呢,自己当时也算是团队中的核心开发成员了,所以当时有幸出了一次差,而且有幸坐了第一次飞机,体验了一下空中交通工具的便捷性。还是回到正题吧,在超图工作的重点有两个,一个是编码一个是支持,编码的过程非常简单,流程化很高。接口设计由架构团队讨论决定之后,底层开发团队根据功能需求完成基础接口,然后由 Java 层面通过 JNI 技术将底层团队提供的 C/C++接口封装起来,当然同时还有.NET 团队在做 CLR 的封装。

JNI 封装的工作性质很简单,主要就是与 C/C++层面的通信,把一堆基础接口攒成一个可用性高的接口,当然这个工作主要有架构师团队完成设计。编码工作中主要注意的东西有一些,异常判断,数组搬移,野指针等等。SDK 作为基础开发平台主要就是模块化,稳定压倒一切。在超图的工作经历,让我对与 JNI 整个的工作机制以及编码方法有了一个大体的了解,来到 喜讯 之后,做了第一个游戏——《黄金矿工喜讯特别版》Android 版本。编码的过程中逐渐开始熟悉 Android 的开发方式以及框架结构,在开发过程中碰到了很多的问题,不过所幸最后产品还是成功的出炉了。据说市场反应还不错,因为这作为公司一个磨练团队的产品,目前还没有后续的开发和维护,只是出了一个版本,对于市场反馈也没有做太多的统计,甚至都没有放到 Google Market 上去,只是在一些国内论坛和第三方市场中做过分享。不过大体了解一些 Android 中开发的猫腻和技巧,Android 由于其开源的特性,有很多东西可以窥探到,在 Android Framework 中有很多带有// TODO 标签的代码段,很多的注释中直接标明“This is a bug”类似的字眼。不过正因为它的开源,很多 Framework 的机制可以自己一一剥开来慢慢瞧,例如对于图像解码中非常容易出现的 OOM 错误,顺着代码链,我们可以看到所有的代码,从 Java=>JNI=>C,最终可以跟踪到 VM 创建时堆大小的初始化,详情可以参见我 这篇博客

虽然最终我们看似已经找到了问题,但是究竟如何解决这个问题呢,目前我还没有找到非常好的方法,因为这个受到了 Framework 的限制,而 Framework 也没有提供非常好的机制来防止该问题的出现,不过也许可以借助异常的捕获来解决该问题,不过本人自己还未做过该方面的尝试。在做完这个游戏之后,又经历了两个软件项目,项目中自己主要负责的是 UI 层面的东西,不过主要的设计和 UE 控制并不由我主要负责,本人主要负责代码实现,主要设计与 UE 控制由设计师来完成。Android 原生的开发环境是 Java,按说开发效率是比较高的,当然这个并不是我自己说的,也是从网络上诸多的报告和大牛们的分析中看到的,至于他们为什么得出这个结论我自己并不是非常明了,我自己比较有感触的就是 Java 相对于 C/C++来说,自由度相对要小,不过基础库非常完备,很多的特性均有平台完成,程序员主要负责的就是逻辑和界面的问题,相对来说会较 C/C++效率高一些 (当然这还是因人而异的)。既然 Java 开发效率要高一些,那么 Android 中的开发效率是否会高一些呢?我看不尽然,Android 虽然提供 Java 的开发环境,但是其框架环境非常庞大和复杂,个人认为比 Java SE 复杂多了很多。Java 只是 Android 开发中的一个敲门砖而已,不过既然已经没有了语言层面上的问题,那么就剩下框架的问题。

然而框架的问题并不是那么的简单,Android 是一个在工程实验室中就被推到市场上的项目,当年 Andy Rubin 创建 Android 具体是什么时候不是很清楚,不过 Andy Rubin 还是 Danger, Inc. 的联合创始人,而 Danger 在 2008 年 2 月份才被 Microsoft 收购。

The company was originally started by former Apple Inc., WebTV and Philips employees Andy Rubin, Joe Britt, and Matt Hershenson. Danger was acquired by Microsoft on 11 February 2008, for a price rumored to be around $500 million (USD).

由此看来这家公司参与者还有 Apple 的身影。再来看看 Android

In July 2005, Google acquired Android Inc., a small startup company based in Palo Alto, California, USA.[20] Android’s co-founders who went to work at Google included Andy Rubin (co-founder of Danger),[21] Rich Miner (co-founder of Wildfire Communications, Inc.),[22] Nick Sears (once VP at T-Mobile),[23] and Chris White (headed design and interface development at WebTV).[24] At the time, little was known about the functions of Android, Inc. other than that they made software for mobile phones.[20] This began rumors that Google was planning to enter the mobile phone market.

从这两个简介中看来 Andy Rubin 的经历不能不说是很神奇啊,曾经供职过 Apple, Philips,然后是 WebTV,Danger,现在是 Google,Andy Rubin 好像一直都是在做移动设备,在该领域他的经验非常的丰富和恐怖。从 Danger 和 Android 的两个简介看来,Andy Rubin 在这两个公司之间是有交集的,不只是职务上,在时间上也是有的,Android 05 年被 Google 收购,08 年 Danger 被 Microsoft 收购。当然我们不管这个了,这只是一个八卦而已。Android 存在的问题很多,昨天看了一下在 Google Code 上的 Android Issues 列表,目前 Open Issues 的数量是 9257,总共 Issues 是 13851,也就是说 Fixed 的 Issued 最多就是 4594 个,比例是 0.331672803,百分比 33%,刚刚 1/3。当然这跟 Android Open 是有一定关系的,任何人都可以提交 Issue,还有很多的 Issue 是重复的。不过我还是认为这个是能说明一些问题的,那就是开发者对于 Android Framework 还不是很满意和放心,当然这其中包括我自己,因为 Android 中有太多@hide 标签的东西以及需要自己去 Hack 的东西,一个 AlertDialog 你想自定义其风格,非常的困难,而系统提供的默认 UI 风格真的非常的一般,从我自己的心眼里来说我非常的不感冒 Google 原生的 UI,我使用的 Legend 自带的 HTC Scense 我就认为非常出色,是一个不可多得的 UI 套件,当然现在市面上已经有了很多很多的 UI 套件,著名一些的国内 UI 套件,有点心科技、MIUI 等等。这确实说明了大家对 Google 原生的 UI 不是很感冒,而且既然你开放,别人能做得比你好干嘛不做啊。

开放带来的问题不只是 UI 的分裂和多样化,还带来了设备的极大丰富和多样,分辨率的多样和分裂更是成为诸多开发者的噩梦。不过其实也不是那么夸张啦,只是需要很大的精力来做好适配,开发者需要更多的时间来调试,设计者需要为多种设备做考虑。这样的情况下,粗看下来,其实设备更多市场越大,用户越多,开发出来的游戏和应用能更大程度地体现价值,更有可能得到不错的回报。这是一个毫无疑问的肯定句,不过能做到适配多机型的软件并不是非常多,因为这个工作量确实不小,关键是设计的工作量不小。Android 开发的难度大不大我想这个因人而异吧,小米团队号称 80 多天弄出来一个 MIUI,那可是非常强大的呢,而我折腾了半年有余,至今未见什么动静。不过我想我碰到的问题每个开发者难免多少都会碰到一些,所谓都在河边走,谁能不湿鞋啊,不湿鞋的那是光着脚走路。

  1. Android 开发中没有良好的可视化控件开发工具,虽然 ADT 中有一个简单的 XML 预览功能,但是确实非常的简陋,不过 ADT 8.0.1 已经好很多了。
  2. Android Framework 对于内存有限制,默认一个 Activity 分配的非 Native 内存由生产商在 VM 初始化确定其值为多大,在 MDPI 的模拟器上是 16M,在 HDPI 的模拟器上是 24M。很多开发者都曾碰到过让人头疼讨厌的 OOM 错误。
  3. 多设备和多分辨率带来的问题,虽然说这可以是一个正面的数据,大不了不支持那么多就行了,但是随便支持几个,你都会或多或少地碰到一些问题,这些问题就是因为分辨率的适配,你的 Layout 甚至可能需要依照分辨率来编写,你的图像资源文件几乎是完全按着分辨率来重新制作的。
  4. UI 的不统一型带来的问题,由于某些 ROM 直接修改了系统默认控件的效果,在很多时候你无法预知你的程序发布出去用户安装之后是一个什么样的运行效果,因为你无法充分测试所有的设备和 ROM,如果非得从根本上让应用在所有设备上效果一致,控件需要自己完全重新实现,这个非常的不现实。
  5. 用户免费心理对开发者的打击甚大,目前在 Android 上收费的软件成功的很少,虽然 Android 号称已经在全球市场上超过了 iPhone,但是目前还仍未出现一个公司能通过在 Android Market 上出售软件实现盈利。遍地开花的破解软件商店,粗制滥造的免费应用充斥着市场等等,无疑让这趟浑水越来越浑了。
  6. 版本的错乱导致的特别版本,针对 NDK 的程序必须在 1.6 以上的机器上运行,Android 几乎是每半年一个大版本,非常有开源社区的风格。每次更新都会带来一些新的特性,那么你能在你的应用中使用吗?我想大多数时候,回答是否定的。市场上的设备很少能及时跟上 Android 版本更新的速度,为了向下兼容,很多时候我们经常是看着已有的轮子不能用,非得自己重新造轮子。
  7. Native 开发环境的恶劣,几乎无法调试的开发,让开发者几近发狂。JNI 开发的特殊性本来就让挺多人挺头疼的了,目前还没有什么好的开发环境,更是让开发者有苦难言啊。
  8. 胜利就在眼前,而你却看不见胜利,多么地令人遗憾啊!
  9. 没有第九点。

相对而言,iPhone 成功的 App Store 和优秀的开发环境和稳定的 SDK,版本相对稳定,机型更是全球唯一确定的那么几种。Symbian 呢,我也不知道说什么,我挺喜欢 Nokia 的,能做这么好的手机的厂商也就是 Nokia 了。WP 7 会是 2011 年微软最成功的产品吗?Visual Studio 的易用性世人皆知,Windows 系统的操作习惯早日深入全世界人民心中,Microsoft 又舍得在这上面砸钱。

我想说的是 WTF,真混乱,趟浑水究竟要到什么时候啊…

I have a dream, One day there is no mobile device in this world.