2013/05/25

Broken usb cable ??

使用 virtualbox, 突然 usb 不能使用, 然後插上去也不會亮燈.
解決方法如下 :
sudo rmmod ehci_hcd; sudo modprobe ehci-hcd

要小心, 最好這兩個動作同時做, 否則 rmmod 後, usb 鍵盤會不能使用了喔.

2013/05/23

小說閱讀器 v1.0.2

v 1.0.2
** 此版本由於修改了閱讀紀錄的設定, 所以升級後會清除原本的閱讀紀錄 **
** 造成不便請見諒 **

* 增加以下小說網站支援
> 金沙中文網

BUGS:
* 修正清除閱讀紀錄, 沒有清除閱讀頁數
* 修正部份導致 FC 的問題
* 修正在某些狀況讀取篇數錯誤的問題

Google Play: 小說閱讀器 v1.0.2

2013/05/19

ImageLoader with volley example

Google 2013/IO, 聽到了 Volley, 以下為測試實用一下.

環境:
SDK: android-17
IDE: eclipse
Device: Moto Atrix with 4.1.2
External Libraries: Volley
git clone --depth 1 https://android.googlesource.com/platform/frameworks/volley


Layout 為一個簡單的 GridView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
android:alwaysDrawnWithCache="false"
android:fadeScrollbars="true"
android:cacheColorHint="@android:color/transparent"
android:numColumns="3"
android:columnWidth="160dp"/>

</RelativeLayout>

griview_row 就是一個很簡單的 imageview 而已
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:id="@+id/imageview"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_centerInParent="true"
android:scaleType="center"
android:contentDescription="@null"/>

</RelativeLayout>

實作過程中, 好像沒投影片那麼簡單, 投影片的 iamgeloader 使用 BitmapLruCache, 原本以為是包含在 volley 的 toolbox, 結果沒有, 必須自己去實作.
而本身 volley 則提供 DiskBaseCache, 簡單講就是暫存到外接記憶體.
Imageloader 的 cache, 必須實作 "ImageLoader.ImageCache" 這個 interface.
下面是實作部份, 此部份使用 picasso裡的 LruCache, 並且改成實作 volley 的 ImageCache.
public class BitmapLruCache implements ImageLoader.ImageCache {
final LinkedHashMap<String, Bitmap> map;
private final int maxSize;

private int size;

/**
* Create a cache using an appropriate portion of the available RAM as the maximum size.
*/
public BitmapLruCache(Context context) {
this(calculateMaxSize(context));
}

/**
* Create a cache with a given maximum size in bytes.
*/
public BitmapLruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("Max size must be positive.");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
}

private Bitmap get(String key) {
if (key == null) {
throw new NullPointerException("key == null");
}

Bitmap mapValue;
synchronized (this) {
mapValue = map.get(key);
if (mapValue != null) {
return mapValue;
}
}

return null;
}

private void set(String key, Bitmap bitmap) {
if (key == null || bitmap == null) {
throw new NullPointerException("key == null || bitmap == null");
}

Bitmap previous;
synchronized (this) {
size += getBitmapBytes(bitmap);
previous = map.put(key, bitmap);
if (previous != null) {
size -= getBitmapBytes(previous);
}
}

trimToSize(maxSize);
}

private void trimToSize(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(
getClass().getName() + ".sizeOf() is reporting inconsistent results!");
}

if (size <= maxSize || map.isEmpty()) {
break;
}

Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= getBitmapBytes(value);
}
}
}

/**
* Clear the cache.
*/
public final void clear() {
trimToSize(-1); // -1 will evict 0-sized elements
}

private static int calculateMaxSize(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0;
int memoryClass = am.getMemoryClass();
if (largeHeap && Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB) {
memoryClass = ActivityManagerHoneycomb.getLargeMemoryClass(am);
}
return 1024 * 1024 * memoryClass / 6;
}

@Override
public Bitmap getBitmap(String url) {
return get(url);
}

@Override
public void putBitmap(String url, Bitmap bitmap) {
set(url, bitmap);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static class ActivityManagerHoneycomb {
static int getLargeMemoryClass(ActivityManager activityManager) {
return activityManager.getLargeMemoryClass();
}
}


@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
private static class BitmapHoneycombMR1 {
static int getByteCount(Bitmap bitmap) {
return bitmap.getByteCount();
}
}

private static int getBitmapBytes(Bitmap bitmap) {
int result;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
result = BitmapHoneycombMR1.getByteCount(bitmap);
} else {
result = bitmap.getRowBytes() * bitmap.getHeight();
}
if (result < 0) {
throw new IllegalStateException("Negative size: " + bitmap);
}
return result;
}
}

基本上主要程式部份, 除了初始話 ImageLoader, 接著就是在 GridView 的 adapter 使用 ImageLoader 就可.
以下只列出部份.
此部份在初始化 ImageLoader, 還有 Volley 最主要的 Request Queue.
RequestQueue mRequestQ;
ImageLoader mImageLoader;
        
mRequestQ = Volley.newRequestQueue(getActivity());
mImageLoader = new ImageLoader(mRequestQ, new BitmapLruCache(getActivity()));

此部份是在取得 image resource.
            holder.container = mImageLoader.get(item.url, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
holder.iv.setImageBitmap(response.getBitmap());
}

@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
}, 160,160);


執行結果如下 :



結論:
初步使用心得, 當 Imageloader 我個人認為就實作方面來說, 似乎還是有一些功夫需要作, 不過使用方面來說算是還滿簡單的.
另外值得一提的是, 對於某些會針對 Http-Header 來做某些行為的網站, 那使用 Volley 則必須要自己去實作 Request.


原始碼下載: VolleyExample.zip

XGallery v1.0.7

v 1.0.7
* Fix some FC problems.
* Change App Icon.

中文說明






v 1.0.7
* 修改部份 FC 問題
* 變更 APP Icon

2013/05/17

論壇瀏覽器 v2.1.2

v 2.1.2 -
* 修正因為 A4TW 改版導致的問題
* 增加以下論壇支援:
> 捷克論壇


Google play store: https://play.google.com/store/apps/details?id=tw.clotai.forumreader

2013/05/16

小說閱讀器 v1.0.0

小說閱讀器目前支援以下線上小說: (會陸續增加)

* Bestory 精品文學 [支援搜尋]
* 卡提諾 小說 [目前暫不支援搜尋]

主要有以下功能:
* 可加入書籤, 方便追蹤小說
* 可紀錄上次讀取位置, 下次會從上次閱讀位置開始
* 可切換顯示主題 (白底黑字 / 黑底白字)
* 支援線上搜尋
* 畫面點擊上半部可往前一頁, 點擊下半不可往後一頁
* 左右滑動可切換上下一篇
* 可切換是否顯示圖片 (開啟圖片顯示, 可能會影響紀錄的閱讀位置)

版本資訊:

v 1.0.0
* 初步功能
* 暫時支援兩個網站

Google Play: 小說閱讀器 v1.0.0


Box: v1.0.0

2013/05/13