ActionBarCompat是Google近期推出的lib,
目的是讓3.0以下的裝置也能夠使用ActionBar,
其實在ActionBarCompat推出之前,
大部份的developer應該都是使用ActionBarSherlock作為backward compatibility的lib!
但我一直都沒有把ActionBarSherlock拿來放在一個production的app,
原因是因為可能有一天它就失去支援,那到時候我就很麻煩,可能要跳進去自己改了!
但現在有了ActionBarCompat,且是Google推出的,支援度應該會較好!
這篇就是教大家怎麼整合
最基本的ActionBarCompat,
讓大家的app可以向下相容actionbar!
首先要先import ActionBarCompat這個lib,
而ActionBarCompat的source code會放在android sdk之中,
路徑應該為:
android-sdk-macosx/extras/android/support/v7/appcompat
接著在你的project點選右鍵->選擇Properties->選擇Android
會看到下圖
接著點選上圖中的Add按鈕,就會看到下圖,
看到下圖後,請選擇android-support-v7-appcompat,
選完以後就會看到下圖,請按下按鈕OK!
完成以後就能在你的project裡面使用actionbar了,只差一些設定了!
1. 先換Style記得換掉values, values-v11, values-v14裡面所有的style.xml,
把AppBaseTheme的parent改成下列的example,
如果你不是一個新的project,你可能有自己的theme,那麼就把他的parent換成下面的吧!
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light">
</style>
2. extend ActionBarActivity接著要把你主要的Activity換成extend ActionBarActivity,如下
package net.kenyang.practiceactionbarcompat;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
3. 修改menu/main.xml你的project應該會有一個預設的main.xml
那麼你需要做兩件事:
- 將root element新增一個attribute
- 替
- element新增一個attribute
如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:actionbar="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/action_settings1"
android:icon="@drawable/ic_launcher"
android:orderInCategory="0"
actionbar:showAsAction="ifRoom"
android:title="@string/action_settings"/>
<item
android:id="@+id/action_settings2"
android:orderInCategory="100"
android:showAsAction="never"
android:title="@string/action_settings"/>
</menu>
注意上面的例子,
第一個item和第二個item有一個attribute不一樣!
就是showAsAction,一個是
actionbar,另一個是
android!
如果你想要這顆menu獨立顯示為一個action item的話,
請改成actionbar,否則用android的話,你永遠看不到那顆action item,
如果是android 3.0以上,它會被隱藏在下圖中右上角的點點點之中!
如果是android 2.x系列,就會在menu裡面!
所以請都改成actionbar:showAsAction!
最後請注意actionbar:showAsAction有很多個選項,
如ifRoom, never, always...etc
可以自己去試試看各自的差別!
只要完成上述三個步驟!
就完成一個很基本的actionbarcompat!
且可以向下相容至2.x的device上!!
在後面幾篇會告訴大家
- 如何用actionbarcompat加入tabs!(這裡)
- swipe to switch tabs.
- style actionbar
Before we start, please make sure your system requirements.
What's do you need?- A Raspberry PI
- A boot SD card with default Raspberry PI image iso (Raspbian "wheezy")
- A USB WiFi device which support "Access Point" mode and the driver is rtl8192cu
1. Install the necessary packages sudo apt-get install hostapd bridge-utils
2. Configure sudo vim /etc/default/hostapd
Add the following line to the bottom of the file.
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Modified the config file
sudo vim /etc/hostapd/hostapd.conf
Add the following lines to the file.
You can change the "ssid", "wpa_passphrase".
Most the others examples use nl80211 as their driver, but Raspberry PI don't have the driver (default).
Therefore I can't start the service hostapd.
However I found some people use rtl871xdrv and they have the related hostapd binary file that supports rtl driver.
So... I use rtl871xdrv.
interface=wlan0
driver=rtl871xdrv
ssid=KenRaspberryPiAP
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=safesync
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
3. Change network interface setting sudo vim /etc/network/interfaces
auto lo
auto br0
iface lo inet loopback
iface br0 inet dhcp
bridge_fd 1
bridge_hello 3
bridge_maxage 10
bridge_stp off
bridge_ports eth0 wlan0
allow-hotplug eth0
iface eth0 inet manual
allow-hotplug wlan0
iface wlan0 inet manual
4. Replace the hostappd binaryDownload
cd /usr/sbin
rm -f hostapd
wget http://dl.dropboxusercontent.com/u/13846584/hostapd
Change Permission
sudo chown root:root hostapd
sudo chmod 755 hostapd
5. Rebootsudo reboot now
After reboot, you should see your own Raspberry PI Access Point(AP).
前篇文章已經說明過GCM,以及和前身C2DM的差異!
這篇主要會講解Android端如何實作,其實和以前在C2DM時差不多
如果要看差異以及一些參數說明,可以到下面幾篇文章去看
第一篇在講
參數說明第二篇在講
流程說明這裡就直接進入主題,
首先一樣要在Manifest檔案中,要有下列的permission,
<permission android:name="net.kenyang.gcm.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="net.kenyang.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
接著就是要新增一個receiver,
而receiver必須聆聽兩個事件,分別為receive以及registration!
<receiver
android:name="net.kenyang.gcm.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="net.kenyang" />
</intent-filter>
</receiver>
再寫code之前,請先確定你的eclipse有裝下面的兩個plugin,
安裝完成以後,請去到你的sdk folder裡面找到下面兩個jar檔,並且include他們兩個!
- android-sdk-macosx/extras/google/gcm/gcm-client/dist/gcm.jar
- android-sdk-macosx/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar
接著開始寫code,
android分為三個部分,
- 向Google 註冊,並且取得registration id
- 傳送id給我們的server
- 準備接收資料
首先是註冊,記得改成你的sender_id!
sender_id就是你的project id,可以到
api console去看你的id,
會有下圖,project number就是你的project id了!
記得把它填入sender_id中!
GoogleCloudMessaging gcm;
String SENDER_ID = "xxxxxxxxxxx";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvRegisterMsg = (TextView) findViewById(R.id.tvRegisterMsg);
context = getApplicationContext();
// initial GCM
gcm = GoogleCloudMessaging.getInstance(this);
// register with Google.
new AsyncTask<Void,String,String>() {
@Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
strRegId = gcm.register(SENDER_ID);
msg = "Device registered, registration id=" + strRegId;
// send id to our server
sendRegIdToServer(strRegId);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
@Override
protected void onPostExecute(String msg) {
tvRegisterMsg.append(msg + "\n");
}
}.execute(null, null, null);
}
接著是第二部分,把id傳送到我們的server,
private void sendRegIdToServer(final String strId) {
new AsyncTask<Void,String,String>() {
@Override
protected String doInBackground(Void... params) {
String strResponseCode = "";
try {
HttpRequestBase request =null;
request = new HttpGet(new URI("http://your_server/storeRegId?id="+strId));
request.addHeader("User-Agent", "Android");
HttpResponse response = Connection.connect((HttpGet)request);
strResponseCode = String.valueOf(response.getStatusLine().getStatusCode());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return strResponseCode;
}
@Override
protected void onPostExecute(String msg) {
tvRegisterMsg.append("status code: " + msg + "\n");
}
}.execute(null, null, null);
}
到了此步驟你在畫面上應該會看到registration_id和status code是200!
如果是上述的結果的話,就代表你向Google註冊成功了!以及也把registration id傳送給我們的server知道了!
接著就來implement receiver的部分!
這個receiver會接收來自Google Server的資料,
並且把資料丟到我們的notification bar當中!
public class GcmBroadcastReceiver extends BroadcastReceiver {
static final String TAG = "GCMDemo";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
@Override
public void onReceive(Context context, Intent intent) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED .equals(messageType)) {
sendNotification("Deleted messages on server: " + intent.getExtras().toString());
} else {
sendNotification("Received: " + intent.getExtras().toString());
}
setResultCode(Activity.RESULT_OK);
}
// Put the GCM message into a notification and post it.
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
new Intent(ctx, Main.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
完成上述以後你就可以開始測試!
只要打開瀏覽器,然後輸入你的site,(http://your_site/
send),
接著你的device上應該就會收到訊息了!
訊息會是一個json格式!