<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Roiding Studio</title>
	<atom:link href="http://www.roiding.com/index.php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.roiding.com</link>
	<description>All things about Android and Mobile 2.0</description>
	<pubDate>Sat, 04 Jul 2009 05:57:57 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>实现拖动效果</title>
		<link>http://www.roiding.com/index.php/archives/211</link>
		<comments>http://www.roiding.com/index.php/archives/211#comments</comments>
		<pubDate>Mon, 09 Mar 2009 02:34:44 +0000</pubDate>
		<dc:creator>猪头小队长</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[android]]></category>

		<category><![CDATA[drag]]></category>

		<category><![CDATA[MotionEvent]]></category>

		<category><![CDATA[OnTouchListener]]></category>

		<category><![CDATA[拖动]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=211</guid>
		<description><![CDATA[废话少说，要实现的效果就是在界面上拖动这一个按钮到处跑。
1. 布局文件

&#60;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&#62;
&#60;LinearLayout xmlns:android=&#34;http://schemas.android.com/apk/res/android&#34;
android:orientation=&#34;vertical&#34; android:layout_width=&#34;fill_parent&#34;
android:layout_height=&#34;fill_parent&#34;&#62;
&#60;Button android:id=&#34;@+id/btn_hello&#34; android:layout_width=&#34;fill_parent&#34;
android:layout_height=&#34;wrap_content&#34; android:text=&#34;@string/hello&#34; /&#62;
&#60;/LinearLayout&#62;

2. 代码


package com.roiding.sample;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;

public class Touch extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final Button btn = (Button) findViewById(R.id.btn_hello);

btn.setOnTouchListener(new OnTouchListener() {
int[] temp = new int[] { 0, 0 };

public boolean onTouch(View v, MotionEvent [...]]]></description>
			<content:encoded><![CDATA[<p>废话少说，要实现的效果就是在界面上拖动这一个按钮到处跑。</p>
<p>1. 布局文件</p>
<pre class="syntax-highlight:xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:orientation=&quot;vertical&quot; android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;&gt;
&lt;Button android:id=&quot;@+id/btn_hello&quot; android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot; android:text=&quot;@string/hello&quot; /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>2. 代码</p>
<pre class="syntax-highlight:java">

package com.roiding.sample;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;

public class Touch extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final Button btn = (Button) findViewById(R.id.btn_hello);

btn.setOnTouchListener(new OnTouchListener() {
int[] temp = new int[] { 0, 0 };

public boolean onTouch(View v, MotionEvent event) {

int eventaction = event.getAction();
Log.i(&quot;&amp;&amp;&amp;&quot;, &quot;onTouchEvent:&quot; + eventaction);

int x = (int) event.getRawX();
int y = (int) event.getRawY();

switch (eventaction) {

case MotionEvent.ACTION_DOWN: // touch down so check if the
temp[0] = (int) event.getX();
temp[1] = y - v.getTop();
break;

case MotionEvent.ACTION_MOVE: // touch drag with the ball
v.layout(x - temp[0], y - temp[1], x + v.getWidth()
- temp[0], y - temp[1] + v.getHeight());

v.postInvalidate();
break;

case MotionEvent.ACTION_UP:
break;
}

return false;
}

});

}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/211/feed</wfw:commentRss>
		</item>
		<item>
		<title>运行后台服务（二）－ 使用技巧</title>
		<link>http://www.roiding.com/index.php/archives/187</link>
		<comments>http://www.roiding.com/index.php/archives/187#comments</comments>
		<pubDate>Fri, 06 Feb 2009 09:31:58 +0000</pubDate>
		<dc:creator>pawa</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[android]]></category>

		<category><![CDATA[Receiver]]></category>

		<category><![CDATA[Service]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=187</guid>
		<description><![CDATA[接着前一部分，我们来讨论一下在具体使用服务时候会碰上一些问题，以及探讨一下解决的办法。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信，又不想让 Service 随着 Activity 退出而退出呢？你可以先 startService() 然后再 bindService()  。当你不需要绑定的时候就执行 unbindService() 方法，执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信，也不会随着 Activity 销毁而销毁了。
提高 Service 优先级
Android 系统对于内存管理有自己的一套方法，为了保障系统有序稳定的运信，系统内部会自动分配，控制程序的内存使用。当系统觉得当前的资源非常有限的时候，为了保证一些优先级高的程序能运行，就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况，多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会，我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background，当前运行的 Activity 一般被标记为 foreground，也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉，只是提高了他的优先级。
有一个方法可以给你更清晰的演示，进入 $SDK/tools 运行命令

# [...]]]></description>
			<content:encoded><![CDATA[<p>接着前一部分，我们来讨论一下在具体使用服务时候会碰上一些问题，以及探讨一下解决的办法。</p>
<p><strong>与 Service 通信并且让它持续运行</strong></p>
<p>如果我们想保持和 Service 的通信，又不想让 Service 随着 Activity 退出而退出呢？你可以先 startService() 然后再 bindService()  。当你不需要绑定的时候就执行 unbindService() 方法，执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信，也不会随着 Activity 销毁而销毁了。</p>
<p><strong>提高 Service 优先级</strong></p>
<p>Android 系统对于内存管理有自己的一套方法，为了保障系统有序稳定的运信，系统内部会自动分配，控制程序的内存使用。当系统觉得当前的资源非常有限的时候，为了保证一些优先级高的程序能运行，就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况，多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会，我们可以用 setForeground(true) 来设置 Service 的优先级。</p>
<p>为什么是 foreground ? 默认启动的 Service 是被标记为 background，当前运行的 Activity 一般被标记为 foreground，也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉，只是提高了他的优先级。</p>
<p>有一个方法可以给你更清晰的演示，进入 $SDK/tools 运行命令</p>
<pre class="syntax-highlight:bash">
# adb shell dumpsys activity|grep oom_adj

Running Norm Proc # 6: oom_adj=  0 ProcessRecord{43635cf0 12689:com.roiding.netraffic/10028}
Running Norm Proc # 5: oom_adj=  7 ProcessRecord{436feda0 12729:com.android.browser/10006}
Running Norm Proc # 4: oom_adj=  8 ProcessRecord{4367e838 12761:android.process.acore/10016}
Running Norm Proc # 3: oom_adj=  8 ProcessRecord{43691cd8 12754:com.google.process.gapps/10000}
Running PERS Proc # 1: oom_adj=-12 ProcessRecord{43506750 5941:com.android.phone/1001}
Running PERS Proc # 0: oom_adj=-100 ProcessRecord{4348fde0 5908:system/1000}
</pre>
<p>返回的一大堆东西，观察 oom_adj 的值，如果是大于 8 一般就是属于 backgroud 随时可能被干掉，数值越小证明优先级越高，被干掉的时间越晚。你看phone的程序是 -12 说明电话就是电话，其他什么都干了了，也的能接电话对吧。另外还有一个 -100 的，更邪乎因为是 system 如果他也完蛋了，你得系统也就挂了，嘿嘿。</p>
<p><strong>用其他方式启动 Service</strong></p>
<p>其实不光能从 Activity 中启动 Service ，还有一个很有用的方法是接收系统的广播，这就要用到 Receiver 。在 Mainfest 文件中配置你得 Receiver 能接收什么样的广播消息，那么即使你得程序没有显示给用户，你的 Service 也能启动。你要做的就是继承 android.content.BroadcastReceiver ，然后实现 onReceive(Context context, Intent intent) 方法，就可以启动你得 Service 了。这里不能 bindService 因为一个 Receiver 是一个短暂存在的对象，所以 bind 是没有什么意义的。</p>
<p><strong>资源消耗</strong></p>
<p>大家都说 G1 的电池太不抗用，这个问题其实我看来跟多是软件的问题。1150毫安的电池不算大，但也不算小了，考虑到 500mhz 的 CPU 还是非常耗电的。因为一个 Service 要长时间后台运行，所以如果你得 Service 太过于消耗资源那电池更用不了多久了。</p>
<p>对于这个问题我有一点点考虑，和大家分享一下。因为一般 Service 都会启动另外的线程不断循环作一些操作，循环频率不易太高。也不要做太过于耗费资源的操作，特别是CPU资源，因为后台 Service 用户看不到，会比较莫名奇妙。具体可以结合 top 以及 logcat 监测使用情况。LOG中如果虚拟机频繁的 GC 应该也说明程序还有很大改进的余地。因为GC 也是很耗费CPU的。可能这些不光 Service 应该注意，只要是移动设备都应该考虑，才能给你的用户最佳的体验。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/187/feed</wfw:commentRss>
		</item>
		<item>
		<title>运行后台服务（一）－ 生命周期</title>
		<link>http://www.roiding.com/index.php/archives/179</link>
		<comments>http://www.roiding.com/index.php/archives/179#comments</comments>
		<pubDate>Fri, 06 Feb 2009 08:48:31 +0000</pubDate>
		<dc:creator>pawa</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[android]]></category>

		<category><![CDATA[Service]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=179</guid>
		<description><![CDATA[作为一款多任务操作系统，如果不能运行后台服务，显然说不过去，Android 当然提供了运行后台程序的方法。而且非常简单易用，只不过有一些小问题需要注意，这个主题分为两部分，第一部分是如何实现一个Service以及他的生命周期，第二部分是对于一个个后台服务应该注意的事项。我们开始吧！
创建服务类

所谓的服务，在Android里被称做 Service，只要继承 android.app.Service 这个抽象类，并且实现其中几个方法就可以了。

public class RoidingService extends android.app.Service {}

里边必须实现的一个方法是 onBind(Intent intent) ，他具体是做什么的我们下边讲。还有两个重要的回调函数需要覆盖，onCreate() 和 onDestroy()。跟 Actitivty 类似，在创建和销毁 Service 时回调这两个函数，达到初始化或退出前保存状态。
服务的生命周期
有了 Service 类我们如何启动他呢，有两种方法：

Context.startService()
Context.bindService()

在同一个应用任何地方调用 startService() 方法就能启动 Service 了，然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台，直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动，其他代码再试图调用 startService() 方法，是不会执行 onCreate() 的，但会重新执行一次 onStart() 。
另外一种 bindService() 方法的意思是，把这个 Service 和调用 Service 的客户类绑起来，如果调用这个客户类被销毁，Service 也会被销毁。用这个方法的一个好处是，bindService() 方法执行后 Service 会回调上边提到的 [...]]]></description>
			<content:encoded><![CDATA[<p>作为一款多任务操作系统，如果不能运行后台服务，显然说不过去，Android 当然提供了运行后台程序的方法。而且非常简单易用，只不过有一些小问题需要注意，这个主题分为两部分，第一部分是如何实现一个Service以及他的生命周期，第二部分是对于一个个后台服务应该注意的事项。我们开始吧！</p>
<p><strong>创建服务类<br />
</strong><br />
所谓的服务，在Android里被称做 Service，只要继承 android.app.Service 这个抽象类，并且实现其中几个方法就可以了。</p>
<pre class="syntax-highlight:java">
public class RoidingService extends android.app.Service {}
</pre>
<p>里边必须实现的一个方法是 onBind(Intent intent) ，他具体是做什么的我们下边讲。还有两个重要的回调函数需要覆盖，onCreate() 和 onDestroy()。跟 Actitivty 类似，在创建和销毁 Service 时回调这两个函数，达到初始化或退出前保存状态。</p>
<p><strong>服务的生命周期</strong></p>
<p>有了 Service 类我们如何启动他呢，有两种方法：</p>
<ul>
<li>Context.startService()</li>
<li>Context.bindService()</li>
</ul>
<p>在同一个应用任何地方调用 startService() 方法就能启动 Service 了，然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台，直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动，其他代码再试图调用 startService() 方法，是不会执行 onCreate() 的，但会重新执行一次 onStart() 。</p>
<p>另外一种 bindService() 方法的意思是，把这个 Service 和调用 Service 的客户类绑起来，如果调用这个客户类被销毁，Service 也会被销毁。用这个方法的一个好处是，bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发，你可以从这里返回一个实现了 IBind 接口的类，在客户端操作这个类就能和这个服务通信了，比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行，使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/179/feed</wfw:commentRss>
		</item>
		<item>
		<title>点太背，我的G1呀！</title>
		<link>http://www.roiding.com/index.php/archives/136</link>
		<comments>http://www.roiding.com/index.php/archives/136#comments</comments>
		<pubDate>Fri, 23 Jan 2009 05:26:33 +0000</pubDate>
		<dc:creator>tempest</dc:creator>
		
		<category><![CDATA[新闻与评论]]></category>

		<category><![CDATA[G1]]></category>

		<category><![CDATA[GPhone]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=136</guid>
		<description><![CDATA[20号中午收到盼望已久的G1，兴奋呀，急不可待的拿出来操作早在模拟机上就已熟悉的软件。Market, Wifi, Gmail, Maps等等，谁知新鲜劲还没有过足24小时，我的G1就罢工了。在用USB充电时忽然PowerOff了，怎么折腾都没反应。联系了Android Dev Support, 对方答复如果没有在新机器上做过任何开发可以process it for a return. 按要求发出相应的信息，2天过去了石沉大海。
——————————————————
Dear Tempest,
Have you done any software development work on this device? If not – we will process it for a return.  We will need the following information from you:
- Purchase order number (2356…)
- IMEI serial number of the phone
- Reason for the return
Please email [...]]]></description>
			<content:encoded><![CDATA[<p>20号中午收到盼望已久的G1，兴奋呀，急不可待的拿出来操作早在模拟机上就已熟悉的软件。Market, Wifi, Gmail, Maps等等，谁知新鲜劲还没有过足24小时，我的G1就罢工了。在用USB充电时忽然PowerOff了，怎么折腾都没反应。联系了Android Dev Support, 对方答复如果没有在新机器上做过任何开发可以process it for a return. 按要求发出相应的信息，2天过去了石沉大海。</p>
<p>——————————————————</p>
<p><span style="font-size: x-small; font-family: Century Gothic;"><span style="font-size: 10pt; font-family: &quot;Century Gothic&quot;;">Dear Tempest,</span></span></p>
<p><span style="font-size: x-small; font-family: Century Gothic;"><span style="font-size: 10pt; font-family: &quot;Century Gothic&quot;;">Have you done any software development work on this device? If not – we will process it for a return.  We will need the following information from you:</span></span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"><span>-<span style="font-size: xx-small; font-family: Times New Roman;"><span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; font-family: &quot;Times New Roman&quot;;"> </span></span></span></span></span><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Purchase order number (2356…)</span></span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"><span>-<span style="font-size: xx-small; font-family: Times New Roman;"><span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; font-family: &quot;Times New Roman&quot;;"> </span></span></span></span></span><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">IMEI serial number of the phone</span></span></p>
<p style="margin-left: 0.5in; text-indent: -0.25in;"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"><span>-<span style="font-size: xx-small; font-family: Times New Roman;"><span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; font-family: &quot;Times New Roman&quot;;"> </span></span></span></span></span><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Reason for the return</span></span></p>
<p><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Please email us the information – we will then forward your email to our Returns Dept for processing.</span></span></p>
<p><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Regards,</span></span></p>
<p><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Android Dev Support </span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/136/feed</wfw:commentRss>
		</item>
		<item>
		<title>如何设置隐藏标题栏和状态栏？</title>
		<link>http://www.roiding.com/index.php/archives/112</link>
		<comments>http://www.roiding.com/index.php/archives/112#comments</comments>
		<pubDate>Sun, 04 Jan 2009 10:06:08 +0000</pubDate>
		<dc:creator>猪头小队长</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[hide titlebar statusbar 隐藏]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=112</guid>
		<description><![CDATA[G1的屏幕的分辨率是320&#215;480，虽说不小但也谈不上大，所以有的应用要使用起来，最好还是希望把状态栏(Status Bar)和标题栏(Title Bar)也隐藏了，这样就可以有更大的屏幕空间给应用程序。


@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

final Window win = getWindow();
// No Statusbar
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

// No Titlebar
requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.mylayout);
}

摘自anddev
]]></description>
			<content:encoded><![CDATA[<p>G1的屏幕的分辨率是320&#215;480，虽说不小但也谈不上大，所以有的应用要使用起来，最好还是希望把状态栏(Status Bar)和标题栏(Title Bar)也隐藏了，这样就可以有更大的屏幕空间给应用程序。</p>
<pre class="syntax-highlight:java">

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

final Window win = getWindow();
// No Statusbar
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

// No Titlebar
requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.mylayout);
}
</pre>
<p>摘自<a href="http://www.anddev.org/hide_statusbar-title_on_qvga_-_getting_screen_resolution-t2689.html" target="_blank">anddev</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/112/feed</wfw:commentRss>
		</item>
		<item>
		<title>伟大的公司输出价值观</title>
		<link>http://www.roiding.com/index.php/archives/106</link>
		<comments>http://www.roiding.com/index.php/archives/106#comments</comments>
		<pubDate>Sun, 14 Dec 2008 15:08:27 +0000</pubDate>
		<dc:creator>pawa</dc:creator>
		
		<category><![CDATA[新闻与评论]]></category>

		<category><![CDATA[roiding]]></category>

		<category><![CDATA[价值观]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=106</guid>
		<description><![CDATA[翻开这期的第一财经周刊，看到主编的开篇文章，一段话醍醐灌顶：
伟大的公司应该有鲜明的形象、强势的企业文化、与消费者体验息息相关的亲和力，或许还应该具有输出价值观的能力
终于明白为什么那些优秀的、伟大的公司让人尊敬和向往。虽然我们现在只是几个人凭借爱好聚在一起，也许我们永远不能被成为伟大，但我们希望我们不但能输出好的产品，而且能输出对社会、对我们热爱的软件开发行业有用的价值观。
我们做有用的、简单易于使用的产品
我们做到我们能做到的最好
我们分享我们的经验，我们保持开放的心态
我们追求永无止境，我们一起努力！
UPDATE：又看到了一篇BLOG，是我们的同行，说出了我们的心声，也是我们要遵循的价值观：
便宜的打败贵的，质量好的打败质量差的，认真的打败轻率的，耐心的打败浮躁的，勤奋的打败懒惰的，有信誉的打败没信誉的……
]]></description>
			<content:encoded><![CDATA[<p>翻开这期的<a href="http://www.china-cbn.com/" target="_blank">第一财经周刊</a>，看到主编的开篇文章，一段话醍醐灌顶：</p>
<blockquote><p>伟大的公司应该有鲜明的形象、强势的企业文化、与消费者体验息息相关的亲和力，或许还应该<strong>具有输出价值观的能力</strong></p></blockquote>
<p>终于明白为什么那些优秀的、伟大的公司让人尊敬和向往。虽然我们现在只是几个人凭借爱好聚在一起，也许我们永远不能被成为伟大，但我们希望我们不但能输出好的产品，而且能输出对社会、对我们热爱的软件开发行业有用的价值观。</p>
<p>我们做有用的、简单易于使用的产品<br />
我们做到我们能做到的最好<br />
我们分享我们的经验，我们保持开放的心态<br />
我们追求永无止境，我们一起努力！</p>
<p>UPDATE：又看到了<a href="http://huajun.w18.net/2008/12/infothinkerwe-will-be-best.html" target="_blank">一篇BLOG</a>，是我们的同行，说出了我们的心声，也是我们要遵循的价值观：</p>
<blockquote><p>便宜的打败贵的，质量好的打败质量差的，认真的打败轻率的，耐心的打败浮躁的，勤奋的打败懒惰的，有信誉的打败没信誉的……</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/106/feed</wfw:commentRss>
		</item>
		<item>
		<title>如何在运行时获得屏幕尺寸？</title>
		<link>http://www.roiding.com/index.php/archives/104</link>
		<comments>http://www.roiding.com/index.php/archives/104#comments</comments>
		<pubDate>Wed, 10 Dec 2008 06:13:02 +0000</pubDate>
		<dc:creator>猪头小队长</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[DisplayMetrics]]></category>

		<category><![CDATA[屏幕尺寸]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=104</guid>
		<description><![CDATA[现在，吵吵闹闹的要生产Android手机的厂商越来越多，从开发者的角度来说，不能不说这是一件好事，毕竟写出来的程序可以顺利的跑在更多的设备上，但是参差不及的硬件选择也给我们带来了很大的麻烦，最直接的就是不同的手机屏幕的尺寸可能不一样，又不能为每种尺寸都设计一套布局，所以就有可能需要在程序运行时来通过屏幕的大小来动态的调整一些布局相关的参数。那如何获得屏幕的大小呢？
在android.app.Activity中提供这样的方法：

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
int screenHeight = dm.heightPixels;

其中，screenWidth就是屏幕的宽度，screenHeight就是屏幕的高度。
如果将手机从肖像模式(竖着拿)变成风景模式(横着拿)，这两个值也会随之改变，所以，也许我们不用这种方法，也可以推算出手机的手持方式，从而来改变一些布局参数。
]]></description>
			<content:encoded><![CDATA[<p>现在，吵吵闹闹的要生产Android手机的厂商越来越多，从开发者的角度来说，不能不说这是一件好事，毕竟写出来的程序可以顺利的跑在更多的设备上，但是参差不及的硬件选择也给我们带来了很大的麻烦，最直接的就是不同的手机屏幕的尺寸可能不一样，又不能为每种尺寸都设计一套布局，所以就有可能需要在程序运行时来通过屏幕的大小来动态的调整一些布局相关的参数。那如何获得屏幕的大小呢？</p>
<p>在android.app.Activity中提供这样的方法：</p>
<pre class="syntax-highlight:java">
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
int screenHeight = dm.heightPixels;
</pre>
<p>其中，screenWidth就是屏幕的宽度，screenHeight就是屏幕的高度。</p>
<p>如果将手机从肖像模式(竖着拿)变成风景模式(横着拿)，这两个值也会随之改变，所以，也许我们不用<a href="http://www.roiding.com/index.php/archives/3">这种方法</a>，也可以推算出手机的手持方式，从而来改变一些布局参数。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/104/feed</wfw:commentRss>
		</item>
		<item>
		<title>又一款山寨视频</title>
		<link>http://www.roiding.com/index.php/archives/93</link>
		<comments>http://www.roiding.com/index.php/archives/93#comments</comments>
		<pubDate>Wed, 10 Dec 2008 05:31:42 +0000</pubDate>
		<dc:creator>pawa</dc:creator>
		
		<category><![CDATA[新闻与评论]]></category>

		<category><![CDATA[OHA]]></category>

		<category><![CDATA[山寨]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=93</guid>
		<description><![CDATA[这是所谓的 Sciphone G2。不过视频模糊的一塌糊涂，只能看个大概，但似乎还比较流畅，也没有太多错误信息。感觉虚拟键盘还不错。就是这个 Android Home Edition V1.0 比较蒙人，从来没看到 GOOGLE 有这样的分法，看来要山寨到底了。不过即便这样，也比那个 OMS 强，这个中国移动以及风险投资支持的 Borqs 播思通信，网站上一个 Andorid 都没出现过，更NB的是号称 “具有完全自主的知识产权”，真不知道是怎么来的，佩服一个！

不管怎么样，似乎山寨离我们越来越近喽……
另外一条新闻，Open Handset Alliance 又增加了14个成员 ARM，华为，华硕，索尼爱立信，东芝，沃达丰这样的重量级玩家在列，另外上边说的 Borqs 也就是这个播思通讯也是成员了，千万别太丢脸了啊。更加期待 2009 的 Android 满天飞了。
]]></description>
			<content:encoded><![CDATA[<p>这是所谓的 Sciphone G2。不过视频模糊的一塌糊涂，只能看个大概，但似乎还比较流畅，也没有太多错误信息。感觉虚拟键盘还不错。就是这个 Android Home Edition V1.0 比较蒙人，从来没看到 GOOGLE 有这样的分法，看来要山寨到底了。不过即便这样，也比那个 OMS 强，这个中国移动以及风险投资支持的 <a href="http://www.borqs.com/index_zh.jsp" target="_blank">B</a><a href="http://www.borqs.com/index_zh.jsp" target="_blank">orqs 播</a><a href="http://www.borqs.com/index_zh.jsp" target="_blank">思通信</a>，网站上一个 Andorid 都没出现过，更NB的是号称 “<a href="http://www.borqs.com/oms_zh.jsp" target="_blank">具有完全自主的知识产权</a>”，真不知道是怎么来的，佩服一个！</p>
<p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="400" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="align" value="middle" /><param name="src" value="http://player.youku.com/player.php/sid/XNTc3MzA4OTY=/v.swf" /><embed type="application/x-shockwave-flash" width="480" height="400" src="http://player.youku.com/player.php/sid/XNTc3MzA4OTY=/v.swf" align="middle"></embed></object></p>
<p>不管怎么样，似乎山寨离我们越来越近喽……</p>
<p><a href="http://www.openhandsetalliance.com/press_120908.html" target="_blank">另外一条新闻</a>，Open Handset Alliance 又增加了14个成员 ARM，华为，华硕，索尼爱立信，东芝，沃达丰这样的重量级玩家在列，另外上边说的 <a href="http://www.borqs.com/index_zh.jsp" target="_blank">Borqs</a> 也就是这个<a href="http://www.borqs.com/index_zh.jsp" target="_blank">播思通讯</a>也是成员了，千万别太丢脸了啊。更加期待 2009 的 Android 满天飞了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/93/feed</wfw:commentRss>
		</item>
		<item>
		<title>Android数据存取之Databases</title>
		<link>http://www.roiding.com/index.php/archives/91</link>
		<comments>http://www.roiding.com/index.php/archives/91#comments</comments>
		<pubDate>Tue, 09 Dec 2008 11:50:22 +0000</pubDate>
		<dc:creator>猪头小队长</dc:creator>
		
		<category><![CDATA[技术与研究]]></category>

		<category><![CDATA[delete]]></category>

		<category><![CDATA[getReadableDatabase]]></category>

		<category><![CDATA[getWritableDatabase]]></category>

		<category><![CDATA[insert]]></category>

		<category><![CDATA[query]]></category>

		<category><![CDATA[SQLite]]></category>

		<category><![CDATA[SQLiteOpenHelper]]></category>

		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=91</guid>
		<description><![CDATA[在Android平台上可以操作数据库，这是第一次接触Android时的惊艳之一。在Android平台上，绑定了SQLite数据库，这个数据库系统也是极具性格的，它的最大的应用场景是嵌入式系统，进一步了解可以参看这里。
如果有JDBC的经验，那么在这里会容易的多。Android中操作数据库首先要通过一个 类：android.database.sqlite.SQLiteOpenHelper。它封装了如何打开一个数据库，其中当然也包含如果数据库不存在 就创建这样的逻辑。看一个例子：

pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = &#34;com.roiding.simple.note&#34;;
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = &#34;notes&#34;;

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(&#34;CREATE TABLE &#34; + NOTES_TABLE_NAME
+ &#34; (id integer primary key autoincrement, name text);&#34;);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(&#34;DROP [...]]]></description>
			<content:encoded><![CDATA[<p>在Android平台上可以操作数据库，这是第一次接触Android时的惊艳之一。在Android平台上，绑定了SQLite数据库，这个数据库系统也是极具性格的，它的最大的应用场景是嵌入式系统，进一步了解可以参看<a href="http://www.sqlite.org/" target="_blank">这里</a>。</p>
<p>如果有JDBC的经验，那么在这里会容易的多。Android中操作数据库首先要通过一个 类：android.database.sqlite.SQLiteOpenHelper。它封装了如何打开一个数据库，其中当然也包含如果数据库不存在 就创建这样的逻辑。看一个例子：</p>
<pre class="syntax-highlight:java">
pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = &quot;com.roiding.simple.note&quot;;
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = &quot;notes&quot;;

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(&quot;CREATE TABLE &quot; + NOTES_TABLE_NAME
+ &quot; (id integer primary key autoincrement, name text);&quot;);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(&quot;DROP TABLE IF EXISTS notes&quot;);
onCreate(db);
}
}
</pre>
<p>这里面，如下的语句需要解释：</p>
<ul>
<li> super(context, DATABASE_NAME, null, DATABASE_VERSION)<br />
数据库连接的初始化，中间的那个null，是一个CursorFactory参数，没有仔细研究这个参数，暂时置空吧。</li>
<li> public void onCreate(SQLiteDatabase db)<br />
这里面的onCreate是指数据库onCreate时，而不是DatabaseHelper的onCreate。也就是说，如果已经指定 database已经存在，那么在重新运行程序的时候，就不会执行这个方法了。要不然，岂不是每次重新启动程序都要重新创建一次数据库了！在这个方法中，完成了数据库的创建工作。也就是那个execSQL()方法。</li>
<li> public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)<br />
在程序的开发维护过程中，数据库的结构可能会有变化，那么这个方法就有用处了。在DatabaseHelper这个对象一创建时，就已经把参数 DATABASE_VERSION传入，这样，如果Android发现此版本与现有版本不一致，就会调用这个onUpgrate方法。于是，可以在这里面实现一些数据的upgrade工作，比如说创建一个临时表，将数据由临时表中转到新的表结构中。需要注意的是，这里面的onUpgrade是在版本不一致时调用，也就是说不管当前需要的版本高于现有版本还是低于现有版本，都会出发这个方法，类似的这种情况，就需要对oldVersion和 newVersion进行判断之后再决定使用什么策略来更新数据。</li>
</ul>
<p>在Android中，数据库存放在 <strong>/data/data/PACKAGE_NAME/databases</strong> 目录下。</p>
<p>接下来就可以使用这个Helper来操作数据库了，操作数据库也就无非是增、删、改、查。先看一个增的例子：</p>
<pre class="syntax-highlight:java">
public static void insert(Context context, String s) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = &quot;notes&quot;;
String nullColumnHack = &quot;id&quot;;

ContentValues values = new ContentValues();
values.put(&quot;name&quot;, &quot;www.roiding.com&quot;);

long id = mOpenHelper.getReadableDatabase().insert(table,
nullColumnHack, values);

mOpenHelper.getReadableDatabase().close();
}
</pre>
<ul>
<li> DatabaseHelper mOpenHelper = new DatabaseHelper(context);<br />
如果和JDBC例子的话，这一步貌似就像是获得了一个Statement，用它就可以操作数据库了。</li>
<li> ContentValues values = new ContentValues();<br />
Android在向数据库中插入数据的时候，要求数据存放到ContentValues中，这里面的ContentValues其实就是一个 Map，Key值是字段名称，Value值是字段的值。这样，也许你会发现一个问题，那数据类型怎么办？其实在SQLite数据库中就是没有数据类型的， 一切都是字符串。</li>
<li>mOpenHelper.getReadableDatabase().insert(table,nullColumnHack, values);<br />
将数据入库，注意这里面有一个nullColumnHack，看文档是和所有字段都是空的记录有关系，我没有去实验他具体的效果，只是随便给他一个字段名称。</li>
</ul>
<p>再看一个查的例子：</p>
<pre class="syntax-highlight:java">
public static void select(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = &quot;notes&quot;;
String[] columns = new String[] { &quot;id&quot;, &quot;name&quot; };
String selection = &quot;id&gt;? and name&lt;&gt;?&quot;;
String[] selectionArgs = new String[] { &quot;0&quot;, &quot;roiding.com&quot; };
String groupBy = null;
String having = null;
String orderBy = &quot;id desc&quot;;
String limit = &quot;1&quot;;

Cursor c = mOpenHelper.getReadableDatabase().query(table,
columns, selection, selectionArgs, groupBy, having, orderBy, limit);

c.moveToFirst();
for (int i = 0; i &lt; c.getCount(); i++) {
String s = c.getString(1);
c.moveToNext();
}
c.close();
mOpenHelper.getReadableDatabase().close();
}
</pre>
<ul>
<li> DatabaseHelper mOpenHelper = new DatabaseHelper(context);<br />
于前文中的相同</li>
<li> mOpenHelper.getReadableDatabase().query();<br />
通过mOpenHelper.getReadableDatabase()，会得到一个SQLiteDatabase类型的只读的数据库连接，在这里直接调用了他的query方法。这个query方法相对复杂，因为他将一个完整的SQL语句拆成了若干个部分：</p>
<ul>
<li> table：表名。相当于SQL的from后面的部分。那如果是多表联合查询怎么办？那就用逗号将两个表名分开，拼成一个字符串作为table的值。</li>
<li> columns：要查询出来的列名。相当于SQL的select后面的部分。</li>
<li> selection：查询条件，相当于SQL的where后面的部分，在这个语句中允许使用“?”，也就是说这个用法和JDBC中的PreparedStatement的用法相似。</li>
<li> selectionArgs：对应于selection的值，selection有几个问号，这里就得用几个值。两者必须一致，否则就会有异常。</li>
<li> groupBy：相当于SQL的group by后面的部分</li>
<li> having：相当于SQL的having后面的部分</li>
<li> orderBy：相当于SQL的order by后面的部分，如果是倒序，或者是联合排序，可以写成类似这样：String orderBy = &#8220;id desc, name&#8221;;</li>
<li> limit：指定结果集的大小，它和Mysql的limit用法不太一样，mysql可以指定从多少行开始之后取多少条，例如“limit 100,10”，但是这里只支持一个数值。</li>
</ul>
</li>
<li> c.moveToFirst();<br />
这一句也比较重要，如果读取数据之前，没有这一句，会有异常。</li>
<li> c.getString(1);<br />
与JDBC一致了，Android不支持按字段名来取值，只能用序号。</li>
</ul>
<p>再看一个删除和修改的例子：</p>
<pre class="syntax-highlight:java">
public static void delete(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = &quot;notes&quot;;
String selection = &quot;id&gt;? and name&lt;&gt;?&quot;;
String[] selectionArgs = new String[] { &quot;0&quot;, &quot;roiding.com&quot; };
String whereClause = selection;
String[] whereArgs = selectionArgs;

mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}
</pre>
<p>有了上面的基础这里就容易理解了，这里的whereClause相当于前面的selection，whereArgs相当于前面的selectionArgs。</p>
<pre class="syntax-highlight:java">
public static void update(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = &quot;notes&quot;;
String selection = &quot;id&gt;? and name&lt;&gt;?&quot;;
String[] selectionArgs = new String[] { &quot;0&quot;, &quot;roiding.com&quot; };
String whereClause = selection;
String[] whereArgs = selectionArgs;

ContentValues values = new ContentValues();
values.put(&quot;name&quot;, &quot;www.roiding.com&quot;);

mOpenHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}
</pre>
<p>这个update的用法，综合select和delete就可以理解。</p>
<p>注意：</p>
<ul>
<li> Cursor和Databases要及时关闭，不然也会有异常。</li>
<li> getWritableDatabase()和getReadableDatabase()在当前的Android版本中貌似可以通用，像上面的insert，用的就是getReadableDatabase。</li>
</ul>
<p>在真实的应用中，会对上面这些基本操作做更高一级的抽象和封装，使之更容易使用。在select时，除了用上述的方法，将分段的SQL语句传进去之外，Android还支持一种方法：使用SQLiteQueryBuilder。如果使用的是上述的分段SQL语句的方法，在Android的内部实现中，也是先将分段的SQL使用SQLiteQueryBuilder的静态方法来生成一个真正的SQL的，而且，我没有看出来使用SQLiteQueryBuilder的优势。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/91/feed</wfw:commentRss>
		</item>
		<item>
		<title>G1 开发机</title>
		<link>http://www.roiding.com/index.php/archives/81</link>
		<comments>http://www.roiding.com/index.php/archives/81#comments</comments>
		<pubDate>Tue, 09 Dec 2008 05:08:11 +0000</pubDate>
		<dc:creator>pawa</dc:creator>
		
		<category><![CDATA[新闻与评论]]></category>

		<category><![CDATA[G1]]></category>

		<guid isPermaLink="false">http://www.roiding.com/?p=81</guid>
		<description><![CDATA[
很好看得花纹哦～～～
Google 和 T-Mobile 联合推出了G1的开发机，详细内容在这里，没有锁定运营商，并且也没有特殊的 bootloader 程序，可以自由使用兼容的电话卡。更重要的是可以自己刷机，终于那一堆源码不止是为虚拟机用了，开始修改那堆源码吧，番茄花园版机器人系统？
$399 的价格倒也算不上贵，当然还需要一些额外的步骤，要注册成为 Android Developer 另外花上 $25。不过比较恼人的是中国大陆还不在能被接受的国家区域之内，台湾，新加坡，日本都在，类似情况和IPHONE如出一折，难道中国的知识产权问题这么严重？想搞到这机器，就期待无所不能的水货 JS 吧，或者紧急联系我们远赴海外的亲友团。
$399 + $25 + $40 (运费) ＝ $464 =￥3155 似乎还是比 JS 们的 G1 ＋解锁便宜哦。不过还是太贵，苦等山寨啊！
]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="aligncenter size-full wp-image-82" title="dev-g1-android1" src="http://www.roiding.com/wp-content/uploads/2008/12/dev-g1-android1.jpg" alt="" width="301" height="250" /></p>
<p style="text-align: left;">很好看得花纹哦～～～</p>
<p style="text-align: left;">Google 和 T-Mobile 联合推出了G1的开发机，详细内容在<a title="Android Dev Phone 1" href="http://code.google.com/android/dev-devices.html" target="_blank">这里</a>，没有锁定运营商，并且也没有特殊的 bootloader 程序，可以自由使用兼容的电话卡。更重要的是可以自己刷机，终于那一堆源码不止是为虚拟机用了，开始修改那堆源码吧，番茄花园版机器人系统？</p>
<p style="text-align: left;">$399 的价格倒也算不上贵，当然还需要一些额外的步骤，要注册成为 Android Developer 另外花上 $25。不过比较恼人的是中国大陆还不在能被接受的国家区域之内，台湾，新加坡，日本都在，类似情况和IPHONE如出一折，难道中国的知识产权问题这么严重？想搞到这机器，就期待无所不能的水货 JS 吧，或者紧急联系我们远赴海外的亲友团。</p>
<p style="text-align: left;">$399 + $25 + $40 (运费) ＝ $464 =￥3155 似乎还是比 JS 们的 G1 ＋解锁便宜哦。不过还是太贵，苦等山寨啊！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.roiding.com/index.php/archives/81/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
