-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
513 lines (507 loc) · 39.3 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Locadz Blog]]></title>
<link href="http://blog.locadz.com//atom.xml" rel="self"/>
<link href="http://blog.locadz.com//"/>
<updated>2012-04-21T17:05:31+08:00</updated>
<id>http://blog.locadz.com//</id>
<author>
<name><![CDATA[Locadz Team]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[透過 Locadz 最大化 App 華文廣告效應]]></title>
<link href="http://blog.locadz.com//blog/2012/04/21/maximize-ad-revenue-in-chinese-market/"/>
<updated>2012-04-21T01:55:00+08:00</updated>
<id>http://blog.locadz.com//blog/2012/04/21/maximize-ad-revenue-in-chinese-market</id>
<content type="html"><![CDATA[<p>在這篇文章中,我將一步步的講解,如何透過 Locadz 來將你的 App 的華文廣告效應最大化。</p>
<div class="section" id="locadz">
<h2>註冊一個 Locadz 的帳號</h2>
<p>註冊 Locadz 帳號是一件簡單的事,我們使用 OpenID 的方式來管理你的帳號,你可以使用任何第三
方的 OpenID 帳號如 GMail or Yahoo 帳號,來登入 Locadz ;我們只保存你的 email 資訊,其
餘資料,仍是保存在你原始的帳號提供者那邊,你也不用煩惱需要多記一組密碼。</p>
<img alt="/images/2012-04-21/sign-up.png" src="http://blog.locadz.com//images/2012-04-21/sign-up.png" />
</div>
<div class="section" id="adunit">
<h2>註冊一個 AdUnit 區塊</h2>
<p>接著,你需要幫你的 App 註冊一個 AdUnit 區塊,AdUnit是 Locadz 管理廣告區域的基本
元素,一個 AdUnit 代表了一個 App 中可以用來顯示的廣告區塊,一個 App 中,可以定意許多的廣告區塊,如下圖。</p>
<p>圖片</p>
<p>各個廣告區塊,可以分別有不同的廣告商設定,例如,螢幕最上端的可以放來自廣告商的廣告,而在營幕
最底部的,則是放您自己其它 App 的廣告或 HouseAD。在 Locadz 這邊,會對各廣告區塊,分別追蹤
廣告的撥放次數及點擊次數。</p>
</div>
<div class="section" id="id1">
<h2>設定 AdUnit 的廣告商</h2>
<p>Locadz 最大的特色就是,能夠讓你「在地化你的廣告商」,在接下來的圖片範例中,將使用幾個廣
告商於不同的區域。</p>
<ul class="simple">
<li>在台灣,50%的流量到 VPon.tw</li>
<li>在台灣,50%的流量到 Kusogi</li>
<li>在中國,100%的流量到 VPon.cn</li>
<li>在其餘的世界各地, 100%的流量到 Google AdMob</li>
</ul>
<p>請遵循下圖的指示,一步步的透過 Web UI ,完成對一個 AdUnit 的設定。</p>
<iframe src="http://files.photosnack.com/iframe/embed.html?hash=pu801yqf&bgcolor=EEEEEE&wmode=window&t=1334913460"
width="600" height="400" seamless="seamless" scrolling="no" frameborder="0" allowtransparency="true"></iframe></div>
<div class="section" id="sdk">
<h2>將 SDK 加入專案</h2>
<div class="tip">
<p class="first admonition-title">Tip</p>
<p class="last">example project is available at <a class="reference external" href="mailto:git@github.com">git@github.com</a>:locadz/android-sdk-example.git
你可以參照這個範例專案來設定 Locadz SDK</p>
</div>
</div>
<div class="section" id="rd-party-sdk">
<h2>下載 3rd Party SDK</h2>
<p>首先,你要自 AdMob, VPon, Kusogi 的網站,下載相關的 Android SDK,</p>
</div>
<div class="section" id="androidmanifest-xml">
<h2>修改 AndroidManifest.xml</h2>
<p>接著,你需要修改你個 AndroidManifest.xml 加入底下這個部份,</p>
<figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
<span class="line-number">44</span>
<span class="line-number">45</span>
<span class="line-number">46</span>
<span class="line-number">47</span>
<span class="line-number">48</span>
<span class="line-number">49</span>
<span class="line-number">50</span>
<span class="line-number">51</span>
<span class="line-number">52</span>
<span class="line-number">53</span>
</pre></td><td class="code"><pre><code class="text"><span class="line"><!-- AdMob integration -->
</span><span class="line"><activity android:name="com.google.ads.AdActivity"
</span><span class="line"> android:configChanges="orientation|keyboard|keyboardHidden|screenLayout|uiMode|screenSize|smallestScreenSize" />
</span><span class="line">
</span><span class="line"><!-- KuAD Integration -->
</span><span class="line"><activity android:name="com.kuad.ADDisplay"/>
</span><span class="line">
</span><span class="line"><!-- VPon integration -->
</span><span class="line"><activity
</span><span class="line"> android:name="com.vpon.adon.android.WebInApp"
</span><span class="line"> android:screenOrientation="portrait"
</span><span class="line"> android:configChanges="orientation|keyboardHidden|navigation|keyboard"
</span><span class="line"> android:label="@string/app_name"/>
</span><span class="line"><activity
</span><span class="line"> android:name="com.vpon.adon.android.CrazyAdRun"
</span><span class="line"> android:configChanges="orientation|keyboardHidden|navigation|keyboard"
</span><span class="line"> android:label="@string/app_name"
</span><span class="line"> android:theme="@android:style/Theme.Translucent" />
</span><span class="line"><activity
</span><span class="line"> android:name="com.vpon.adon.android.webClientHandler.QRActivity"
</span><span class="line"> android:finishOnTaskLaunch = "true"
</span><span class="line"> android:clearTaskOnLaunch = "true"
</span><span class="line"> android:configChanges="keyboardHidden|navigation|keyboard"/>
</span><span class="line"><activity
</span><span class="line"> android:name="com.vpon.adon.android.webClientHandler.ShootActivity"
</span><span class="line"> android:finishOnTaskLaunch = "true"
</span><span class="line"> android:clearTaskOnLaunch = "true"
</span><span class="line"> android:configChanges="keyboardHidden|navigation|keyboard"/>
</span><span class="line"><activity
</span><span class="line"> android:name="com.googleing.zxinging.client.android.HelpActivity"
</span><span class="line"> android:finishOnTaskLaunch = "true"
</span><span class="line"> android:clearTaskOnLaunch = "true"
</span><span class="line"> android:configChanges="keyboardHidden|navigation|keyboard"/>
</span><span class="line"><activity
</span><span class="line"> android:name="com.googleing.zxinging.client.android.CaptureActivity"
</span><span class="line"> android:finishOnTaskLaunch = "true"
</span><span class="line"> android:clearTaskOnLaunch = "true"
</span><span class="line"> android:configChanges="orientation|keyboardHidden"
</span><span class="line"> android:screenOrientation="landscape"
</span><span class="line"> android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
</span><span class="line"> android:windowSoftInputMode="stateAlwaysHidden">
</span><span class="line"> <intent-filter>
</span><span class="line"> <action android:name="com.googleing.zxinging.client.android.SCAN"/>
</span><span class="line"> <category android:name="android.intent.category.DEFAULT"/>
</span><span class="line"> </intent-filter>
</span><span class="line"></activity>
</span><span class="line"><!-- end of Vpon -->
</span><span class="line">
</span><span class="line"><!-- set required permission -->
</span><span class="line"><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
</span><span class="line"><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</span><span class="line"><uses-permission android:name="android.permission.INTERNET"/>
</span><span class="line"><uses-permission android:name="android.permission.READ_PHONE_STATE" />
</span></code></pre></td></tr></table></div></figure></div>
<div class="section" id="adunitlayout-ui-xml">
<h2>將 AdUnitLayout 加入 ui.xml</h2>
<p>最後是把 AdUnitLayout 放置到 UI 上,用來顯示廣告的區塊,同時,你要把這個區會的 ID 設定在這邊
,ADUNIT ID可以從網頁上得知,ADUNIT ID的格式為 <strong>00000000-0000-0000-0000-000000000000</strong> 的32位元字串。</p>
<figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class="xml"><span class="line"><span class="nt"><com.locadz.AdUnitLayout</span>
</span><span class="line"> <span class="na">android:id=</span><span class="s">"@+id/adwhirl_layout"</span>
</span><span class="line"> <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
</span><span class="line"> <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
</span><span class="line"> <span class="na">locadz:adunit_id=</span><span class="s">"${YOUR_ADUNIT_ID}"</span> <span class="nt">/></span>
</span></code></pre></td></tr></table></div></figure></div>]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Lesson Learned form Developing Locadz SDK]]></title>
<link href="http://blog.locadz.com//blog/2012/04/20/lesson-learned-from-developing-locadz-sdk/"/>
<updated>2012-04-20T23:07:00+08:00</updated>
<id>http://blog.locadz.com//blog/2012/04/20/lesson-learned-from-developing-locadz-sdk</id>
<content type="html"><![CDATA[<div class="section" id="introduction">
<h2>Introduction</h2>
<p>市面上大部份講 Android 的書,多數都是在講 API 要怎麼樣使用,但是,許多的書都沒有提到一個重要的問題,就是什
麼是 UI Thread (有時被稱做Main Thread) ,為什麼要有 UI Thread 以及為什麼不可以在 UI Thread 中執行耗時間的運算。</p>
<p>在本文中,我講談一談我們在開發Locadz SDK所使用到的一些技巧。</p>
</div>
<div class="section" id="ui-thread">
<h2>UI Thread</h2>
<p>UI Thread是Android(or other GUI library)用來處理 Event 的 thread ,這些 Event 可能是使用者處發的,如
Touch Event,或者是其它程式或者是系統底層的事件,如 Intent 或 <a class="reference external" href="http://developer.android.com/reference/android/location/LocationListener.html">Location Updates</a>.</p>
<p>在 UI Thread 處理完一個事件後, UI Thread 會重畫整個 Application ,而前面這句話解釋了處理 ANR 的兩個原則</p>
<ul class="simple">
<li>UI事件的處理要越快越好,在處理完前,UI不會有反應</li>
<li>UI的更新,一定要發生在UI Thread,要不然,要等到下次UI Event被處發時才會一併被處理</li>
</ul>
</div>
<div class="section" id="lesson-i-use-weakreference-to-avoid-strong-reference-and-memory-leak">
<h2>Lesson I: Use WeakReference to Avoid Strong Reference and Memory Leak</h2>
<p>有許多的文章談到如何用 <a class="reference external" href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a> 或 <a class="reference external" href="http://stackoverflow.com/questions/3197335/restful-api-service/3197456#3197456">ResultReceiver</a> 來把需要大量運算的程式,放在另一個 Thread 來做處理。</p>
<p>然而,這些範例都有著一個常備忽略的問題,那就是,這些 AsyncTask or ResultReceiver 常會把前景的Activity包進來
,如果說你的程式只有一個 Activity 的話,這或許不是什麼問題,但是若是你的 App 有多個畫面的話,這些在背景執行的程
式可能就會讓你的程式有 memory leak 的問題;如某家廣告商的 SDK 就有此問題。</p>
<p>一個可能的發生狀況是,Activity A透過 AsyncTask 去遠端下載一個圖片來顯示在 <em>Activity A</em> 之上,但因為某些因素
(如忘了設 connection timeout),這個下載的程緒卡住了,既使 User 以從 <em>Activity A</em> 切換到 <em>Activity B</em> 之
上,這個 <em>Activity A</em> 還是不會被 GC 回收掉。</p>
<p>要避開因為有個 Strong Reference 造成 Activity 無法被回收的問題,我們在把有可能被回收的物件傳到另一個 Thread 中
被延後執行時,必需用 <a class="reference external" href="http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html">WeakReference</a> 包住這個物件;如此一來,當Garbage Collector碰到一個已經不在前景的 Activity
時,Garbage Collector會把這物件處理掉,如此一來,就不會有 memory leak 的問題。</p>
<figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
</pre></td><td class="code"><pre><code class="java"><span class="line"><span class="cm">/**</span>
</span><span class="line"><span class="cm"> * AsyncTask to Load Image</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">DownloadImagesTask</span> <span class="kd">extends</span> <span class="n">AsyncTask</span><span class="o"><</span><span class="n">Uri</span><span class="o">,</span> <span class="n">Void</span><span class="o">,</span> <span class="n">Bitmap</span><span class="o">></span> <span class="o">{</span>
</span><span class="line">
</span><span class="line"> <span class="n">WeakReference</span><span class="o"><</span><span class="n">imageview</span><span class="o">></span> <span class="n">imageViewWeakReference</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
</span><span class="line">
</span><span class="line"> <span class="kd">public</span> <span class="nf">DownloadImagesTask</span><span class="o">(</span><span class="n">ImageView</span> <span class="n">imageView</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">imageViewWeakReference</span> <span class="o">=</span> <span class="k">new</span> <span class="n">WeakReference</span><span class="o"><</span><span class="n">Imageview</span><span class="o">>(</span><span class="n">imageView</span><span class="o">);</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="nd">@Override</span>
</span><span class="line"> <span class="kd">protected</span> <span class="n">Bitmap</span> <span class="nf">doInBackground</span><span class="o">(</span><span class="n">Uri</span><span class="o">...</span> <span class="n">uri</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="k">return</span> <span class="nf">downloadImage</span><span class="o">(</span><span class="n">uri</span><span class="o">);</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="nd">@Override</span>
</span><span class="line"> <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onPostExecute</span><span class="o">(</span><span class="n">Bitmap</span> <span class="n">result</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">ImageView</span> <span class="n">imageView</span> <span class="o">=</span> <span class="n">imageViewWeakReference</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
</span><span class="line"> <span class="k">if</span> <span class="o">(</span><span class="n">imageView</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">imageView</span><span class="o">.</span><span class="na">setImageBitmap</span><span class="o">(</span><span class="n">result</span><span class="o">);</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="kd">private</span> <span class="n">Bitmap</span> <span class="nf">downloadImage</span><span class="o">(</span><span class="n">Uri</span> <span class="n">url</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="o">...</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure></div>
<div class="section" id="lesson-ii-use-intentservice-to-run-business-logic">
<h2>Lesson II: Use IntentService to Run Business Logic</h2>
<p>AsyncTask是 Android 最常被用來處理複雜運算時用的工具,透過AsyncTask,我們可以在背景處裡
一些複雜的運算,再把結果放回前景之上。</p>
<p>但據我的經驗,使用 AsyncTask 同時間來擔任 MVC 中的 View & Controller 的工作,最後往往是
把程式碼弄成一團麵線。因此,在開發 Locadz SDK 時,我們把一些跟 UI 無關的運算,都切出來
變成 IntentService 或者是非 Inner class 的 AsyncTask ,把所有的運算邏輯從 Activity 中切出
來,增加重用的可能。</p>
<p>然後運算的結果,再透過 <a class="reference external" href="http://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)">getHandler().post(…)</a> 更新到 UI 之上.</p>
<figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
<span class="line-number">44</span>
<span class="line-number">45</span>
<span class="line-number">46</span>
<span class="line-number">47</span>
<span class="line-number">48</span>
<span class="line-number">49</span>
<span class="line-number">50</span>
<span class="line-number">51</span>
<span class="line-number">52</span>
<span class="line-number">53</span>
<span class="line-number">54</span>
<span class="line-number">55</span>
<span class="line-number">56</span>
<span class="line-number">57</span>
</pre></td><td class="code"><pre><code class="java"><span class="line"><span class="cm">/** Service that retrieve the ad unit allocations from external source and cache locally in SharedPreference. */</span>
</span><span class="line"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AdUnitAllocationService</span> <span class="kd">extends</span> <span class="n">IntentService</span> <span class="o">{</span>
</span><span class="line">
</span><span class="line"> <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">CACHE_EXPIRATION_PERIOD</span> <span class="o">=</span> <span class="mi">30</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="o">;</span> <span class="c1">// 30 minutes.</span>
</span><span class="line">
</span><span class="line"> <span class="kd">private</span> <span class="kd">final</span> <span class="kd">static</span> <span class="n">String</span> <span class="n">PREFS_STRING_TIMESTAMP</span> <span class="o">=</span> <span class="s">"timestamp"</span><span class="o">;</span>
</span><span class="line"> <span class="kd">private</span> <span class="kd">final</span> <span class="kd">static</span> <span class="n">String</span> <span class="n">PREFS_STRING_CONFIG</span> <span class="o">=</span> <span class="s">"config"</span><span class="o">;</span>
</span><span class="line">
</span><span class="line"> <span class="c1">// response code for possible result.</span>
</span><span class="line"> <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">RESULT_OK</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
</span><span class="line">
</span><span class="line"> <span class="kd">public</span> <span class="nf">AdUnitAllocationService</span><span class="o">()</span> <span class="o">{</span>
</span><span class="line"> <span class="kd">super</span><span class="o">(</span><span class="n">AdUnitAllocationService</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getCanonicalName</span><span class="o">());</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="nd">@Override</span>
</span><span class="line"> <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onHandleIntent</span><span class="o">(</span><span class="n">Intent</span> <span class="n">intent</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line">
</span><span class="line"> <span class="n">AdUnitContext</span> <span class="n">adUnitContext</span> <span class="o">=</span>
</span><span class="line"> <span class="o">(</span><span class="n">AdUnitContext</span><span class="o">)</span> <span class="n">intent</span><span class="o">.</span><span class="na">getParcelableExtra</span><span class="o">(</span><span class="n">IntentConstants</span><span class="o">.</span><span class="na">EXTRA_ADUNIT_CONTEXT</span><span class="o">);</span>
</span><span class="line">
</span><span class="line"> <span class="n">AdUnitAllocation</span> <span class="n">adUnitAllocation</span> <span class="o">=</span> <span class="n">getAdUnitAllocation</span><span class="o">(</span><span class="n">adUnitContext</span><span class="o">);</span>
</span><span class="line">
</span><span class="line"> <span class="k">if</span> <span class="o">(</span><span class="n">adUnitAllocation</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">Ration</span> <span class="n">ration</span> <span class="o">=</span> <span class="n">getRandomRation</span><span class="o">(</span><span class="n">adUnitAllocation</span><span class="o">.</span><span class="na">getRations</span><span class="o">());</span>
</span><span class="line">
</span><span class="line"> <span class="c1">// send response through ResultReceiver.</span>
</span><span class="line"> <span class="n">ResultReceiver</span> <span class="n">receiver</span> <span class="o">=</span> <span class="n">intent</span><span class="o">.</span><span class="na">getParcelableExtra</span><span class="o">(</span><span class="n">IntentConstants</span><span class="o">.</span><span class="na">EXTRA_RECEIVER</span><span class="o">);</span>
</span><span class="line">
</span><span class="line"> <span class="n">Bundle</span> <span class="n">resultData</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
</span><span class="line"> <span class="n">resultData</span><span class="o">.</span><span class="na">putString</span><span class="o">(</span><span class="n">IntentConstants</span><span class="o">.</span><span class="na">EXTRA_ADUNIT_ID</span><span class="o">,</span> <span class="n">adUnitContext</span><span class="o">.</span><span class="na">getAdUnitId</span><span class="o">());</span>
</span><span class="line"> <span class="n">resultData</span><span class="o">.</span><span class="na">putSerializable</span><span class="o">(</span><span class="n">IntentConstants</span><span class="o">.</span><span class="na">EXTRA_RATION</span><span class="o">,</span> <span class="n">ration</span><span class="o">);</span>
</span><span class="line"> <span class="n">resultData</span><span class="o">.</span><span class="na">putSerializable</span><span class="o">(</span><span class="n">IntentConstants</span><span class="o">.</span><span class="na">EXTRA_EXTRA</span><span class="o">,</span>
</span><span class="line"> <span class="n">adUnitAllocation</span><span class="o">.</span><span class="na">getExtra</span><span class="o">());</span>
</span><span class="line">
</span><span class="line"> <span class="n">receiver</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="n">RESULT_OK</span><span class="o">,</span> <span class="n">resultData</span><span class="o">);</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="cm">/**</span>
</span><span class="line"><span class="cm"> * Select a random ration form the provided rations.</span>
</span><span class="line"><span class="cm"> * @param rations the candidates.</span>
</span><span class="line"><span class="cm"> * @return a random ration from the candidates.</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"> <span class="kd">private</span> <span class="n">Ration</span> <span class="nf">getRandomRation</span><span class="o">(</span><span class="n">List</span><span class="o"><</span><span class="n">Ration</span><span class="o">></span> <span class="n">rations</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="c1">//...</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="cm">/**</span>
</span><span class="line"><span class="cm"> * Get the allocation configuration for the adunit.</span>
</span><span class="line"><span class="cm"> * @param adUnitContext the context of the adunit.</span>
</span><span class="line"><span class="cm"> * @return the allocation configuration for the adunit.</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"> <span class="n">AdUnitAllocation</span> <span class="nf">getAdUnitAllocation</span><span class="o">(</span><span class="n">AdUnitContext</span> <span class="n">adUnitContext</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="c1">//...</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure></div>
<div class="section" id="lesson-iii-use-disk-cache-instead-of-main-memory-cache">
<h2>Lesson III: Use Disk Cache instead of (Main) Memory Cache</h2>
<p>底下的圖表,是Jeff Dean發表的,在談的是讀取資料的的效率,我們把這幾個數字先記起來,
再加一個代表UI設計時人體覺得是即時反應的反應時間上限 100 ms。然後我們再來談 Android UI 的設計。</p>
<img alt="/images/2012-04-20/numbers-everyone-should-know.png" src="http://blog.locadz.com//images/2012-04-20/numbers-everyone-should-know.png" />
<p>大家可以看到 Main Memory Reference(0.001ms) 與 Disk Seek(10ms) Disk Read(30ms) 的重大差
距,然而,後者的數字在 Mobile Phone 上就不是這樣了。在 Mobile Phone 上,傳統的硬碟扮演的角色,
被NAND Flash Memory, External SD Card所取代了。在存取效率上 NAND Flash Memory 雖然不
比 RAM 快,但是,也仍是 seek time ~1ms 的狠角色。</p>
<p>這 1ms 的負擔,雖比 0.001ms 的負擔高上百倍,以上,但是在 100ms 這UI 反應需求上,卻又變得很渺小了。</p>
<p>因此,在這邊,我會建議大家,若是有 cache 的需求時,直接往 <a class="reference external" href="http://developer.android.com/guide/topics/data/data-storage.html#filesInternal">Internal Storage</a> 塞吧,不要放
在Main memory上,或用個SoftReferenceMap包著。</p>
</div>
<div class="section" id="lesson-iv-make-all-public-method-async-to-avoid-ui-update-issue">
<h2>Lesson IV: Make All Public Method Async to Avoid UI Update Issue</h2>
<p>在上面第一個範例中有個錯誤,那就是DownloadImagesTask.onPostExecute()會在呼叫DownloadImagesTask.execute(…)的
那個 Thread 上執行,如果說,很不幸的,這個 DownloadImagesTask 並不是從 UI Thread 上來呼叫的話,那
麼,imageView.setImageBitmap(result)便有可能不會即時更新到UI之上。</p>
<p>如果你的開發環境會有這種問題,在包在層層呼叫後,無法確保 Method 是否是在 UI Thread 上執行;那麼我
會建議你把會更新 UI 的 Method ,標成 protected ,然後開放一個 public async method 出來,範例如下:</p>
<figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
</pre></td><td class="code"><pre><code class="java"><span class="line"><span class="cm">/**</span>
</span><span class="line"><span class="cm"> * Remove old ad views and push the new one.</span>
</span><span class="line"><span class="cm"> *</span>
</span><span class="line"><span class="cm"> * @param subView the adview to push.</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"><span class="kd">protected</span> <span class="kt">void</span> <span class="nf">pushSubView</span><span class="o">(</span><span class="n">ViewGroup</span> <span class="n">subView</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="c1">//....</span>
</span><span class="line"><span class="o">}</span>
</span><span class="line">
</span><span class="line"><span class="cm">/**</span>
</span><span class="line"><span class="cm"> * submit a push view request to Android's handler. This will remove</span>
</span><span class="line"><span class="cm"> * old ad view and push a new one to this layout asynchronously.</span>
</span><span class="line"><span class="cm"> *</span>
</span><span class="line"><span class="cm"> * @param subView the adview to push.</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"><span class="kd">public</span> <span class="kt">void</span> <span class="nf">submitPushSubViewRequest</span><span class="o">(</span><span class="n">ViewGroup</span> <span class="n">subView</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">Log</span><span class="o">.</span><span class="na">d</span><span class="o">(</span><span class="n">LOG_TAG</span><span class="o">,</span> <span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Scheduled pushSubView(%s)"</span><span class="o">,</span> <span class="n">subView</span><span class="o">));</span>
</span><span class="line"> <span class="n">getHandler</span><span class="o">().</span><span class="na">post</span><span class="o">(</span><span class="k">new</span> <span class="n">ViewAdRunnable</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">subView</span><span class="o">));</span>
</span><span class="line"><span class="o">}</span>
</span><span class="line">
</span><span class="line">
</span><span class="line"><span class="cm">/**</span>
</span><span class="line"><span class="cm"> * Runnable runs on the Main Thread that pushes an AdView to the layout.</span>
</span><span class="line"><span class="cm"> */</span>
</span><span class="line"><span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">ViewAdRunnable</span> <span class="kd">implements</span> <span class="n">Runnable</span> <span class="o">{</span>
</span><span class="line">
</span><span class="line"> <span class="kd">private</span> <span class="kd">final</span> <span class="n">WeakReference</span><span class="o"><</span><span class="n">Adunitlayout</span><span class="o">></span> <span class="n">locadzLayoutWeakReference</span><span class="o">;</span>
</span><span class="line">
</span><span class="line"> <span class="kd">private</span> <span class="n">ViewGroup</span> <span class="n">subView</span><span class="o">;</span>
</span><span class="line">
</span><span class="line"> <span class="kd">public</span> <span class="nf">ViewAdRunnable</span><span class="o">(</span><span class="n">AdUnitLayout</span> <span class="n">layout</span><span class="o">,</span> <span class="n">ViewGroup</span> <span class="n">subView</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">locadzLayoutWeakReference</span> <span class="o">=</span> <span class="k">new</span> <span class="n">WeakReference</span><span class="o"><</span><span class="n">Adunitlayout</span><span class="o">>(</span><span class="n">layout</span><span class="o">);</span>
</span><span class="line"> <span class="k">this</span><span class="o">.</span><span class="na">subView</span> <span class="o">=</span> <span class="n">subView</span><span class="o">;</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line">
</span><span class="line"> <span class="nd">@Override</span>
</span><span class="line"> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
</span><span class="line"> <span class="n">AdUnitLayout</span> <span class="n">locadzLayout</span> <span class="o">=</span> <span class="n">locadzLayoutWeakReference</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
</span><span class="line"> <span class="k">if</span> <span class="o">(</span><span class="n">locadzLayout</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span><span class="line"> <span class="n">locadzLayout</span><span class="o">.</span><span class="na">pushSubView</span><span class="o">(</span><span class="n">subView</span><span class="o">);</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"> <span class="o">}</span>
</span><span class="line"><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure></div>]]></content>
</entry>
</feed>