Month: September 2012

[問題] 遇到 INSTALL_FAILED_INSUFFICIENT_STORAGE 怎麼辦

在安裝 android app 時如果發生 INSTALL_FAILED_INSUFFICIENT_STORAGE 的錯誤就表示系統空間用完了

解決辦法:

1. 新增一個支援 SD card 的 AVD,並將 app 安裝在 SD 上

並修改 AndroidManifest.xml 增加 android:installLocation=”preferExternal”

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mypackage"
    android:versionCode="1"
    android:versionName="1.0" 
    android:installLocation="preferExternal"
    >

2. 增加 partition size (須套用在一個新的尚未啓動過的 AVD 上才會有效用

./emulator -avd my_avd_name -partition-size 128

或是在 elcipse 中設置參數

Tags :

[問題] 如何得到 iOS 裝置畫面的寬高

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
Tags :

[問題] 如何判斷裝置為 iPhone 還是 iPad

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
   // iPad style UI
} else {
   // iPhone and iPod touch style UI
}
Tags :

[問題] 遇到 com.google.android.gsf package couldn’t be found 怎麼辦?

這是因為使用到 Android 的模擬器。只要重新創建一個 Google APIs 的模擬器就可以解決這個問題。

Tags : ,

[教學] Google Cloud Messaging (GCM) Service 訊息推播

事前準備

  • Google API project。需要新增 Project 及  API Key。
  • 推播 Server。需要一個推播 Server 發送推播訊息。
  • gcm.jargoogle 所提供的相關 library。

推播訊息格式

如果你是使用 google 提供的 sdk,那他已經把相關格式包裝好了,不需要去理會格式。

如果想只到完整格式內容可參考 gcm#request

新增一個 Google API project

透過下面的步驟你會得到

  1. Sender ID,client 端用來註冊得到 Registeration ID
  2. API Key,server 端用來發送訊息

步驟很簡單,請參考 GCM Document

安裝 gcm.jar

在 Eclipse 內,開啓 Android SDK Manager

安裝 Extras > Google Cloud Messaging for Android Library,所下載的檔案會放置在

YOUR_SDK_ROOT/extras/google/gcm

「註」如果沒有看到安裝選項,

  1. 請先更新 Android SDK Manage > Tools > SDK Manager (rev. 20)
  2. Help > Install New Software > Android Developer Toolkit ADT

APP 端設定

請參考 Writting the Android Application

這邊會需要用到上面所申請到的 SENDER_ID 去註冊一組 REGISTERATION_ID,然後把這個 REGISTERATION_ID 上傳至 Server 用來作為辨識該處裝置的 ID。

註冊

String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
   GCMRegistrar.register(this, SENDER_ID);
}
ServerUtilities.register(context, regId);

接收提醒

相較於 apple 將提醒功能由底層自動處理掉節省不少步驟,android 則是透過 GCMIntentServiceonMessage(Context context, Intent intent) 讓開發者自行編輯提醒內容

protected void onMessage(Context context, Intent intent) {
   // 這裡提取的 message, 主要是server端 addData時所帶入的部份
   String message = intent.getStringExtra("message");
   displayMessage(context, message);
   // notifies user
   generateNotification(context, message);
};

Server端範例

請參考 Writting the Android Server-side Application

這邊會用到先前所申請到的 API_KEY 用來作為與 google server 溝通時的 key。

// 產生一個 sender instance
Sender sender = new Sender(API_KEY);
Message message = new Message.Builder().addData("message", "Hello World!").build();
// 發送訊息到 device
sender.send(message, REGISTERATION_ID, 5);

相關文章

Tags : , ,

[教學] Apple Push Notification (APN) Service 訊息推播

事前準備

  • iPhone 或是 iPad。推播功能無法在模擬器上使用。
  • iOS 開發者賬號。需要新增 App ID 以及建立相關憑證。
  • 推播 Server。需要一個推播 Server 發送推播訊息。

推播訊息格式

APN 是使用 json 作為傳遞的格式

{
   "aps":
   {
      "alert":"訊息內容",
      "sound":"default",    
      "badge":1
    }
 }

訊息內容(payload)有256 bytes 的長度限制,所以在傳遞時最好把空白字元省略。

{"aps":{"alert":"my message","sound":"default","badge"=1}}

詳信內容可參考 Push Notificaiton Programming Guide

產生憑證 (certificate)

透過下面的步驟你將會得到一系列的檔案

  1. MyPush.certSigningRequest
  2. MyPushKey.p12
  3. aps_development.cer
  4. MyPushCert.pem
  5. MyPushKey.pem
  6. ck.pem (這是我們最後真正會用到的檔案)

1. 產生 Certificate Signing Request (CSR)

到 iOS Provision Protal 申請憑證會需要 CSR

產生步驟:

1. 在你的 mac 電腦內開啓 Keychain Access,然後從選單內選擇 Request a Certificate From a Certificate Authority

2.在下一步的畫面內填寫email 以及 name,記得要選擇 Save to disk,然後就會產生出 MyPush.certSigningRequest 的檔案

3. 匯出 private key

回到 KeyChain Access 的主畫面,在右上方搜尋框內輸入 “MyPush” 應該會看到剛剛建立的key。然後選擇 private key -> Export My Push。將檔案存成 MyPushKey.p12 以及設定密碼 (passphrase)

2. 產生 SSL certificate

這裡需要登入 iOS Provisioning Portal。我將會省略申請 APP ID 的步驟。

1. Enable for Apple Push Notification

進入 App ID 的設定畫面 (Configure App ID),點選 Enable for Apple Push Notification。你會看到兩個憑證

Development Push SSL Certificate – 在開發過程中使用這組

Production Push SSL Cerificate – 上架時使用這組

(憑證有效期限為一年,記得要重新申請,不然會失效。)

我們這次先設定 Development Push SSL Certificate

2. 下載 SSL Certificate

Enable For Apple Push Notification Service 後,點選 Configure。他會要求你提供前面產生的 CSR 檔案。

將下載下來的檔案存成 aps_development.cer

3. 產生 CK.PEM 檔案

打開 Terminal,進入剛所產生檔案的位置

1. 將 .cer 轉換成 .pem

openssl x509 -in aps_development.cer -inform der -out MyPushCert.pem

2. 將 .p12 轉換成 .pem,這邊會要求你輸入之前所設定的密碼。

$ openssl pkcs12 -nocerts -out MyPushKey.pem -in MyPushtKey.p12
Enter Import Password: 
MAC verified OK
Enter PEM pass phrase: 
Verifying - Enter PEM pass phrase:

3. 最後將兩個 pem 檔案合併

cat MyPushCert.pem MyPushKey.pem &gt; ck.pem

APP 端設定 (更新 iOS 8)

修改 MyPushAppDelegate.m

註冊  push notification

在 didFinishLaunchingWithOptions 內加入下面程式碼

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
   self.window.rootViewController = self.viewController;
   [self.window makeKeyAndVisible]; 
   ...
   [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
		(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
   return YES; 
}

////////////////////////////////////////////////////////////
/// iOS 8.0 更新
////////////////////////////////////////////////////////////

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
{
   [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
   [[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
   [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeNewsstandContentAvailability];
}

接收 device token

在 didRegisterForRemoteNotificationsWithDeviceToken 內加入下面程式碼

這裡也是很好的時機點將所收到的 device token 資料傳到 APN Server

- (void)application:(UIApplication*)application
         didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
 
    NSString *tokenStr = [deviceToken description];
    NSString *pushToken = [[[tokenStr 
      stringByReplacingOccurrencesOfString:@"" withString:@""] 
      stringByReplacingOccurrencesOfString:@" " withString:@""];
 
   // 將所收到的 device token 資料傳到 APN Server
}

「註」在 APP 開啓的情況下,是不會收到APN的,所以記得測試的時候要先將 APP 關閉

Server端範例

<?php
 
// 要發送裝置的 device token
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';
 
// 私鑰的密碼
$passphrase = 'password';
 
$message = 'Hello World!';
 
////////////////////////////////////////////////////////////////////////////////
 
$ctx = stream_context_create();
// 帶入 ck.pem
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
 
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', 
      $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
 
$body['aps'] = array('alert' => $message, 'sound' => 'default');
$payload = json_encode($body);
$msg = chr(0).pack('n', 32).pack('H*', $deviceToken).pack('n', strlen($payload)).$payload;
// 送出訊息
fwrite($fp, $msg, strlen($msg));
fclose($fp);
?>
Tags : , , , ,

[問題] 如何使用 NSDateFormatter

Pattern Result (in a particular locale)
yyyy.MM.dd G ‘at’ HH:mm:ss zzz 1996.07.10 AD at 15:08:56 PDT
EEE, MMM d, ”yy Wed, July 10, ’96
h:mm a 12:08 PM
hh ‘o”clock’ a, zzzz 12 o’clock PM, Pacific Daylight Time
K:mm a, z 0:00 PM, PST
yyyyy.MMMM.dd GGG hh:mm aaa 01996.July.10 AD 12:08 PM
NSDateFormatter *df = [[NSDateFormatter alloc]init];
df.dateFormat = @"yy/M/d h:m";
NSDate *date = [df dateFromString:[dict objectForKey:@"12/03/31 9:21"]];
Tags : ,

[問題] iOS開發時如何取得安裝目錄中的 document 路徑

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"xxx.png"];
Tags : ,

[問題] 如何產生&解析 CSV 格式文字

NSString* csvStr = @"編號,標題,名稱,類型";
NSArray *array = [csvStr componentsSeparatedByString:@","];
for (NSString* key in array) {
   NSLog(@"key : %@\n",key);
}
NSString *composedCvsStr = [array componentsJoinedByString:@","];

逗號分隔型取值格式(英文全稱為Comma Separated Values,簡稱CSV)。在CSV中,數據的欄位由逗號分開,程序通過讀取文件重新創建正確的欄位

Tags : , ,

[問題] 如何使用 objective-c 內的剪貼簿 UIPasteboard

UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = @"複製內容";
pasteboard.image = myImage;
pasteboard.URL = myURL;
pasteboard.color = myColor;
Tags : ,