Câu trả lời ngắn gọn, nếu bạn đang nhắm mục tiêu ~ API cấp 7, là "Không". Tình hình có thể đã được cải thiện trong các API sau nhưng vì nó ...Tôi rất muốn khuyên bạn nên tránh SyncAdapter hoàn toàn; tài liệu này rất kém và quản lý tài khoản/xác thực "tự động" có giá cao vì API cho nó cũng phức tạp và không được ghi chép. Điều này một phần của API đã không được nghĩ đến thông qua các trường hợp sử dụng tầm thường nhất.
Vì vậy, đây là mẫu mà tôi đã kết thúc. Bên trong các hoạt động của tôi, tôi đã có một bộ xử lý với một bổ sung đơn giản từ một lớp cha tùy chỉnh Handler (có thể kiểm tra cho một bool m_bStopped
):
private ResponseHandler mHandler = new ResponseHandler();
class ResponseHandler extends StopableHandler {
@Override
public void handleMessage(Message msg) {
if (isStopped()) {
return;
}
if (msg.what == WebAPIClient.GET_PLANS_RESPONSE) {
...
}
...
}
}
Các hoạt động sẽ gọi yêu cầu REST của như hình dưới đây. Lưu ý, trình xử lý được chuyển qua lớp WebClient (lớp trợ giúp để xây dựng/tạo các yêu cầu HTTP, v.v.). WebClient sử dụng trình xử lý này khi nó nhận được phản hồi HTTP cho thông điệp quay lại hoạt động và cho nó biết dữ liệu đã được nhận và, trong trường hợp của tôi, được lưu trữ trong cơ sở dữ liệu SQLite (mà tôi muốn giới thiệu). Trong hầu hết các Hoạt động, tôi sẽ gọi mHandler.stopHandler();
trong onPause()
và mHandler.startHandler();
trong onResume()
để tránh phản hồi HTTP được báo hiệu trở lại Hoạt động không hoạt động, v.v ... Đây là một cách tiếp cận khá mạnh mẽ.
final Bundle bundle = new Bundle();
bundle.putBoolean(WebAPIRequestHelper.REQUEST_CREATESIMKITORDER, true);
bundle.putString(WebAPIRequestHelper.REQUEST_PARAM_KIT_TYPE, sCVN);
final Runnable runnable = new Runnable() { public void run() {
VendApplication.getWebClient().processRequest(null, bundle, null, null, null,
mHandler, NewAccountActivity.this);
}};
mRequestThread = Utils.performOnBackgroundThread(runnable);
Handler.handleMessage()
được gọi trên chuỗi chính. Vì vậy, bạn có thể dừng các hộp thoại tiến trình của mình ở đây và thực hiện các thao tác khác một cách an toàn.
tôi tuyên bố một ContentProvider:
<provider android:name="au.com.myproj.android.app.webapi.WebAPIProvider"
android:authorities="au.com.myproj.android.app.provider.webapiprovider"
android:syncable="true" />
Và thực hiện nó để tạo và quản lý truy cập vào db SQLite:
public class WebAPIProvider extends ContentProvider
Vì vậy, bạn có thể có được con trỏ trên cơ sở dữ liệu trong hoạt động của mình như thế này :
mCursor = this.getContentResolver().query (
WebAPIProvider.PRODUCTS_URI, null,
Utils.getProductsWhereClause(this), null,
Utils.getProductsOrderClause(this));
startManagingCursor(mCursor);
Tôi tìm thấy lớp org.apache.commons.lang3.text.StrSubstitutor
là imme rất hữu ích trong việc xây dựng các yêu cầu XML vụng về theo yêu cầu của API REST mà tôi đã tích hợp với ví dụ. trong WebAPIRequestHelper
Tôi có các phương pháp trợ giúp như:
public static String makeAuthenticateQueryString(Bundle params)
{
Map<String, String> valuesMap = new HashMap<String, String>();
checkRequiredParam("makeAuthenticateQueryString()", params, REQUEST_PARAM_ACCOUNTNUMBER);
checkRequiredParam("makeAuthenticateQueryString()", params, REQUEST_PARAM_ACCOUNTPASSWORD);
valuesMap.put(REQUEST_PARAM_APIUSERNAME, API_USERNAME);
valuesMap.put(REQUEST_PARAM_ACCOUNTNUMBER, params.getString(REQUEST_PARAM_ACCOUNTNUMBER));
valuesMap.put(REQUEST_PARAM_ACCOUNTPASSWORD, params.getString(REQUEST_PARAM_ACCOUNTPASSWORD));
String xmlTemplate = VendApplication.getContext().getString(R.string.XMLREQUEST_AUTHENTICATE_ACCOUNT);
StrSubstitutor sub = new StrSubstitutor(valuesMap);
return sub.replace(xmlTemplate);
}
Tôi sẽ thêm vào URL điểm cuối thích hợp.
Dưới đây là một số chi tiết khác về cách lớp WebClient thực hiện yêu cầu HTTP. Đây là phương thức processRequest()
được gọi trước đó trong Runnable. Chú ý tham số handler
được sử dụng để thông báo kết quả trở lại ResponseHandler
Tôi đã mô tả ở trên. Các syncResult
là trong tham số được sử dụng bởi các SyncAdapter để làm ngược lại theo cấp số nhân vv Tôi sử dụng nó trong executeRequest()
, gia tăng số lỗi khác nhau của nó vv Một lần nữa, rất kém tài liệu và một PITA để có được làm việc. parseXML()
tận dụng tuyệt vời Simple XML lib.
public synchronized void processRequest(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult, Handler handler, Context context)
{
// Helper to construct the query string from the query params passed in the extras Bundle.
HttpUriRequest request = createHTTPRequest(extras);
// Helper to perform the HTTP request using org.apache.http.impl.client.DefaultHttpClient.
InputStream instream = executeRequest(request, syncResult);
/*
* Process the result.
*/
if(extras.containsKey(WebAPIRequestHelper.REQUEST_GETBALANCE))
{
GetServiceBalanceResponse xmlDoc = parseXML(GetServiceBalanceResponse.class, instream, syncResult);
Assert.assertNotNull(handler);
Message m = handler.obtainMessage(WebAPIClient.GET_BALANCE_RESPONSE, xmlDoc);
m.sendToTarget();
}
else if(extras.containsKey(WebAPIRequestHelper.REQUEST_GETACCOUNTINFO))
{
...
}
...
}
Bạn nên đặt một số thời gian chờ trên yêu cầu HTTP để ứng dụng không đợi mãi nếu dữ liệu di động bị loại bỏ hoặc chuyển từ Wifi sang 3G. Điều này sẽ gây ra một ngoại lệ để được ném nếu thời gian chờ xảy ra.
// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 30000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT) in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 30000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient client = new DefaultHttpClient(httpParameters);
Vì vậy, tổng thể, SyncAdapter và tài khoản công cụ là một nỗi đau tổng số và chi phí cho tôi rất nhiều thời gian cho không đạt được. ContentProvider khá hữu ích, chủ yếu cho hỗ trợ con trỏ và giao dịch. Cơ sở dữ liệu SQLite thực sự tốt. Và lớp Handler thật tuyệt vời.Tôi sẽ sử dụng lớp AsyncTask bây giờ thay vì tạo các Threads của riêng bạn như tôi đã làm ở trên để sinh ra các yêu cầu HTTP.
Tôi hy vọng lời giải thích rambling này sẽ giúp ai đó một chút.
Tôi đang vật lộn với [thiết lập tương tự] (http://stackoverflow.com/questions/11906172/synchronize-android-client-and-rest-server). Có lẽ bạn có thể giúp đỡ. – JJD