OKHttp 基本使用紀錄

OKHttp 是支援HTTP & HTTP/2 的開源框架,透過它可以很方便發送HTTP請求。
具有以下特性:
1.API設計簡單,可以透過幾行code即可發送HTTP請求
2.支援同步,異步請求。同步請求會block目前的Thread,異步請求則不會block

OKHttp官網連結

最新版本釋出

以下紀錄最基本的get, post, post with json format 的使用方式。


1.相依性


在 module 的 build.gradle 加入
dependencies {  
...
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
}

Note:目前(2018/09/28)最新版本為3.11.0

2. Using in code


為了封裝OKHttp建立了OKHttpWrapper 類別,外部皆透過該類別來使用OKHttp。
OKHttpWrapper.java
import android.util.Log;  
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.json.JSONObject;

public class OKHttpWrapper {

private static final String TAG = OKHttpWrapper.class.getSimpleName();

private static OkHttpClient sOKHttpClient = new OkHttpClient();

public static void sendGet(String URL, Map<String, String> requestParameter, Callback callback) {
Set<String> keys = requestParameter.keySet();
for (String value : keys) {
URL = new StringBuilder(URL + "&" + value + "=" + requestParameter.get(value)).toString();
}
Request request = new Request.Builder().url(URL).build();
Call call = sOKHttpClient.newCall(request);
call.enqueue(callback);
}

public static void sendPost(String URL, Map<String, String> requestParameter, Callback callback) {
FormBody.Builder builder = new FormBody.Builder();
Set<String> keys = requestParameter.keySet();
for (String key : keys) {
builder.add(key, requestParameter.get(key));
}

Request request = new Request.Builder().url(URL).post(builder.build()).build();

Call call = sOKHttpClient.newCall(request);
call.enqueue(callback);
}

public static void sendPostWithJSONFormat(String URL, Map<String, String> requestParameter,
Callback callback) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(JSON, new JSONObject(requestParameter).toString());
Request request = new Request.Builder().url(URL).post(requestBody).build();
Call call = sOKHttpClient.newCall(request);
call.enqueue(callback);
}

}

第19行建立OKHttpClient實體,各個請求皆透過該實體來動作。
第21行sendGet方法為發送GET使用,第1個參數為接收請求的URL,第2個為請求的參數,第3個參數為發送請求之後的回應。
第31行sendPost方法為發送POST使用,第1個參數為接收請求的URL,第2個為請求的參數,第3個參數為發送請求之後的回應。
第44行sendPostWithJSONFormat方法為發送POST但參數的格式為JSON,第1個參數為接收請求的URL,第2個為請求的參數,第3個參數為發送請求之後的回應。

可以看到透過OKHttp發送請求相當簡單,接下來示範外部如何呼叫OKHttpWrapper。接收請求的Server使用httpbin
以下為外部
  private void testSendRequest(String name, String id) {  
Map<String, String> httpParameter = new HashMap<>();
httpParameter.put("Name", name);
httpParameter.put("ID", id);

OKHttpWrapper.sendPostWithJSONFormat(
"http://httpbin.org/post", httpParameter, new Callback() {
@Override
public void onFailure(Call call, IOException e) {

}

@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, TAG+" response:"+response.body().string());
}
});
}

第2~4行為組裝請求的參數。
第6行呼叫OKHttpWrapper的sendPostWithJSONFormat方法
第1個參數為為接受請求的URL,第2個參數為請求的參數,第3個參數為發送請求後的回應,其中onFailure為請求失敗的回應。onResponse則為請求成功的回應。
        testSendRequest("Foxx", "999");  
testSendRequest("Peter", "000");
testSendRequest("May", "111");

Output
 "json": {  
"ID": "999",
"Name": "Foxx"
},

"json": {
"ID": "000",
"Name": "Peter"
},

"json": {
"ID": "111",
"Name": "May"
},

 

Orignal From: OKHttp 基本使用紀錄

Arrays.binarySearch 直接使用於 android resource 的問題

為了方便使用陣列常常會直接在array.xml中宣告2個互相對應的陣列 e.g.,
  <string-array name="type">  
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
</string-array>
<string-array name="code">
<item>A</item>
<item>C</item>
<item>B</item>
<item>E</item>
<item>F</item>
<item>G</item>
<item>D</item>
</string-array>

若直接在code中使用Arrays.binsearch 會出現 index 錯誤 e.g.,
        String[] targetArray = getResources().getStringArray(R.array.type);  
int index = Arrays.binarySearch(targetArray, 3);
String[] codeArray = getResources().getStringArray(R.array.code);

原因是因為Arrays.binarySearch只能使用在已經排序(自然排序)過的陣列。

若該陣列還未排序會丟出Exception,說明index有問題。

比較快的解決方式就是自己寫取得對應的元素 e.g.,
    private int findSpecifyIndexInArray(String[] targetArray, String specify){  
for (int i = 0; i < targetArray.length; ++i) {
if (targetArray[i].equals(specify)) {
return i;
}
}
return -1;
}

String[] targetArray = getResources().getStringArray(R.array.type);
int index = findSpecifyIndexInArray(targetArray, 3);
String[] codeArray = getResources().getStringArray(R.array.code);

 

Orignal From: Arrays.binarySearch 直接使用於 android resource 的問題

Google Cloud Source Repositories 如何將本地端已存在的repo推送到遠端

狀況:本地端已存在git repo,現在想將本地端的repo推送到遠端的新repo

1.先到GCSR新增遠端新repo
https://source.cloud.google.com/repos ->點擊新增存放區->點擊建立新的存放區->點擊繼續->輸入存放區名稱->選擇已存在專案或新增專案->點擊建立

2.建立本地端repo的認證並推送到遠端
在"請選取將程式碼推送至存放區的選項:"選擇"從本機 Git 存放區推送程式碼"
->在"選取您偏好的驗證方式:"選擇"手動產生的憑證" ->點擊 1.產生及儲存Git憑證->將Configure Git 頁面中的 Windows Users 程式碼複製並貼到本地端的git bash -> 移動到本地端專案路徑並進行 2. 進行將 Cloud Repository 新增為遠端存放區:(這裡注意最好編輯成1行再貼到git bash,如 git remote add google https://xxxx)->最後進行 3.從本機 Git 存放區推送程式碼:
(注意若出現
fatal: remote error:  


Invalid authentication credentials.

Please generate a new identifier:
https://source.developers.google.com/new-password

代表要重新產生憑證,到https://source.developers.google.com/auth/start?scopes=https://www.googleapis.com/auth/cloud-platform
選擇登入帳號,將顯示的程式碼貼到git bash)

 

3.完成後在GCSR的repo便可看到推送的內容。

Orignal From: Google Cloud Source Repositories 如何將本地端已存在的repo推送到遠端

Google Cloud Source Repositories 試用紀錄

GCSR(Google Cloud Source Repositories) 是 google 推出以 git 為基礎的程式碼代管服務。

原先我的side project是自己建git server來放置source code,後來因為硬體故障等等

自己維護需要花費不少時間和成本,加上本身也是google 的愛好者,最後選擇GCSR來試試。

首先談談GCSR的缺點,基本上最大麻煩的點為google 提供的repository必須依附於google cloud platform(GCP)上的專案。

也就是說你必須先了解基本的GCP使用方式才能開始用GCSR。

第2個麻煩的點在於create, clone repository在官方教學中必須透過 google cloud sdk才能使用(也許可以透過別的方式但還未試出),也就是說你必須先安裝 google cloud sdk才能開始使用GCSR。

第3個麻煩的點在於免費版的限制,如下







免費方案
超量


最多 5 位使用者
每位專案使用者每月 $1 美元 (專案使用者達 5 位以上時)

50 GB 儲存空間
每 GB 儲存空間 每月 $0.10 美元

50 GB 輸出
每 GB 輸出每月 $0.10 美元



若以上3個限制您都還可以接受,那就繼續往下看吧。

首先提供官網GCSR的說明。若想直接參考使用方式請看quick start。

1.在Google Cloud Platform建立專案
建議新增獨立的GCP專案來放置repository避免和其他的專案混淆。

2.安裝Google Cloud SDK
安裝SDK的目的就是用來新增,複製專案(應該是可以透過其他方式來做到但還未試出)。
注意安裝完成之後還需要進行初始化的動作,參考這裡

3.安裝git
Windows 官方推薦使用git-scm

Linux就用command line安裝吧

4.使用Google Cloud SDK(gcloud command line) 建立 repository
gcloud source repos create hello-world

clone repo 到本地端
gcloud source repos clone hello-world

從官網看起來似乎只有 create和clone需要使用 gcloud

其它的操作就可以使用一般的git指令,如 git add, git commit, git push等等

5. GCSR UI
當然就像github,gitlab等等,GCSR也有提供repository的UI操作。
以下為repository的介面,存放區即為repository


以下是搶先試用版的畫面


Orignal From: Google Cloud Source Repositories 試用紀錄

使用 RingtoneManager 播放提示音(Notification),鬧鐘(Alarm),來電鈴聲(Ringtone)

1.播放預設的提示音。
  public static void playDefaultNotification(Context context) {
    Uri defaultNotificationURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    Ringtone soundOfDefaultNotification = RingtoneManager.getRingtone(context, defaultNotificationURI);
    soundOfDefaultNotification.play();
  }
其中RingtoneManager.TYPE_NOTIFICATION為提示音的設定。

若想播放預設的鬧鐘只要改為RingtoneManager.TYPE_ALARM
播放預設的鬧鐘只要改為RingtoneManager.TYPE_RINGTONE

2.播放裝置內其他的提示音。
首先取得裝置內的提示音清單。

  public static Map<String, String> getSoundTitleAndUri(Context context, int type) {
    RingtoneManager manager = new RingtoneManager(context);
    manager.setType(type);
    Cursor cursor = manager.getCursor();

    Map<String, String> titleAndUri = new HashMap<>();
    while (cursor.moveToNext()) {
      String title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
      String id = cursor.getString(RingtoneManager.ID_COLUMN_INDEX);
      String uri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX);
      titleAndUri.put(title, uri+"/"+id);
    }

    return titleAndUri;
  }
 
使用的方式如下(取得提示音的清單)

    getSoundTitleAndUri(context, RingtoneManager.TYPE_NOTIFICATION);
回傳的Map其key值即為提示音的名稱,value值為提示音的Uri。

若想取得的是鬧鐘清單,只要改為RingtoneManager.TYPE_ALARM即可
若想取得的是來電鈴聲清單,只要改為RingtoneManager.TYPE_RINGTONE即可

若把該Map印出來如下。
key:Alloy value:content://media/internal/audio/media/89
key:Arc value:content://media/internal/audio/media/90
key:Bezel value:content://media/internal/audio/media/91
...
Alloy為提示音的名稱,其URI為 content://media/internal/audio/media/89

最後要播放指定的提示音如下

  public static void playSound(Context context, String uri) {
    Uri soundUri = Uri.parse(uri);
    Ringtone sound = RingtoneManager.getRingtone(context, soundUri);
    sound.play();
  }
使用的方法為

  playSound(context,"content://media/internal/audio/media/89");//play Alloy

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Affiliate Network Reviews