Clean up sample code to look better.

Change-Id: I91bdfc7ce2d32f23dc7ce9a4276cba37d7fafc42
This commit is contained in:
Megha Joshi
2010-08-13 10:57:39 -07:00
parent 4779ab6f9a
commit c51da235c2
15 changed files with 430 additions and 300 deletions

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync;
public class Constants {
@@ -26,7 +25,5 @@ public class Constants {
/**
* Authtoken type string.
*/
public static final String AUTHTOKEN_TYPE =
"com.example.android.samplesync";
public static final String AUTHTOKEN_TYPE = "com.example.android.samplesync";
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.authenticator;
import android.app.Service;
@@ -26,7 +25,9 @@ import android.util.Log;
* and returns its IBinder.
*/
public class AuthenticationService extends Service {
private static final String TAG = "AuthenticationService";
private Authenticator mAuthenticator;
@Override
@@ -47,9 +48,8 @@ public class AuthenticationService extends Service {
@Override
public IBinder onBind(Intent intent) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG,
"getBinder()... returning the AccountAuthenticator binder for intent "
+ intent);
Log.v(TAG, "getBinder()... returning the AccountAuthenticator binder for intent "
+ intent);
}
return mAuthenticator.getIBinder();
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.authenticator;
import android.accounts.AbstractAccountAuthenticator;
@@ -33,6 +32,7 @@ import com.example.android.samplesync.client.NetworkUtilities;
* authenticating accounts in the com.example.android.samplesync domain.
*/
class Authenticator extends AbstractAccountAuthenticator {
// Authentication Service context
private final Context mContext;
@@ -41,34 +41,25 @@ class Authenticator extends AbstractAccountAuthenticator {
mContext = context;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle addAccount(AccountAuthenticatorResponse response,
String accountType, String authTokenType, String[] requiredFeatures,
Bundle options) {
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
String authTokenType, String[] requiredFeatures, Bundle options) {
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE,
authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) {
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
Bundle options) {
if (options != null && options.containsKey(AccountManager.KEY_PASSWORD)) {
final String password =
options.getString(AccountManager.KEY_PASSWORD);
final boolean verified =
onlineConfirmPassword(account.name, password);
final String password = options.getString(AccountManager.KEY_PASSWORD);
final boolean verified = onlineConfirmPassword(account.name, password);
final Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, verified);
return result;
@@ -76,45 +67,35 @@ class Authenticator extends AbstractAccountAuthenticator {
// Launch AuthenticatorActivity to confirm credentials
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRMCREDENTIALS, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRM_CREDENTIALS, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions) {
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle loginOptions) {
if (!authTokenType.equals(Constants.AUTHTOKEN_TYPE)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE,
"invalid authTokenType");
result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
return result;
}
final AccountManager am = AccountManager.get(mContext);
final String password = am.getPassword(account);
if (password != null) {
final boolean verified =
onlineConfirmPassword(account.name, password);
final boolean verified = onlineConfirmPassword(account.name, password);
if (verified) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE,
Constants.ACCOUNT_TYPE);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
result.putString(AccountManager.KEY_AUTHTOKEN, password);
return result;
}
@@ -123,33 +104,25 @@ class Authenticator extends AbstractAccountAuthenticator {
// Activity that will prompt the user for the password.
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE,
authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
response);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
/**
* {@inheritDoc}
*/
@Override
public String getAuthTokenLabel(String authTokenType) {
if (authTokenType.equals(Constants.AUTHTOKEN_TYPE)) {
if (Constants.AUTHTOKEN_TYPE.equals(authTokenType)) {
return mContext.getString(R.string.label);
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response,
Account account, String[] features) {
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
String[] features) {
final Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
return result;
@@ -159,24 +132,20 @@ class Authenticator extends AbstractAccountAuthenticator {
* Validates user's password on the server
*/
private boolean onlineConfirmPassword(String username, String password) {
return NetworkUtilities.authenticate(username, password,
null/* Handler */, null/* Context */);
return NetworkUtilities
.authenticate(username, password, null/* Handler */, null/* Context */);
}
/**
* {@inheritDoc}
*/
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions) {
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle loginOptions) {
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE,
authTokenType);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRMCREDENTIALS, false);
intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(AuthenticatorActivity.PARAM_CONFIRM_CREDENTIALS, false);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.authenticator;
import android.accounts.Account;
@@ -42,16 +41,28 @@ import com.example.android.samplesync.client.NetworkUtilities;
* Activity which displays login screen to the user.
*/
public class AuthenticatorActivity extends AccountAuthenticatorActivity {
public static final String PARAM_CONFIRMCREDENTIALS = "confirmCredentials";
/** The Intent flag to confirm credentials. **/
public static final String PARAM_CONFIRM_CREDENTIALS = "confirmCredentials";
/** The Intent extra to store password. **/
public static final String PARAM_PASSWORD = "password";
/** The Intent extra to store username. **/
public static final String PARAM_USERNAME = "username";
/** The Intent extra to store authtoken type. **/
public static final String PARAM_AUTHTOKEN_TYPE = "authtokenType";
/** The tag used to log to adb console. **/
private static final String TAG = "AuthenticatorActivity";
private AccountManager mAccountManager;
private Thread mAuthThread;
private String mAuthtoken;
private String mAuthtokenType;
/**
@@ -62,14 +73,18 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
/** for posting authentication attempts back to UI thread */
private final Handler mHandler = new Handler();
private TextView mMessage;
private String mPassword;
private EditText mPasswordEdit;
/** Was the original caller asking for an entirely new account? */
protected boolean mRequestNewAccount = false;
private String mUsername;
private EditText mUsernameEdit;
/**
@@ -77,6 +92,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
*/
@Override
public void onCreate(Bundle icicle) {
Log.i(TAG, "onCreate(" + icicle + ")");
super.onCreate(icicle);
mAccountManager = AccountManager.get(this);
@@ -85,19 +101,15 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
mUsername = intent.getStringExtra(PARAM_USERNAME);
mAuthtokenType = intent.getStringExtra(PARAM_AUTHTOKEN_TYPE);
mRequestNewAccount = mUsername == null;
mConfirmCredentials =
intent.getBooleanExtra(PARAM_CONFIRMCREDENTIALS, false);
mConfirmCredentials = intent.getBooleanExtra(PARAM_CONFIRM_CREDENTIALS, false);
Log.i(TAG, " request new: " + mRequestNewAccount);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
setContentView(R.layout.login_activity);
getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
android.R.drawable.ic_dialog_alert);
mMessage = (TextView) findViewById(R.id.message);
mUsernameEdit = (EditText) findViewById(R.id.username_edit);
mPasswordEdit = (EditText) findViewById(R.id.password_edit);
mUsernameEdit.setText(mUsername);
mMessage.setText(getMessage());
}
@@ -152,7 +164,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
*
* @param the confirmCredentials result.
*/
protected void finishConfirmCredentials(boolean result) {
private void finishConfirmCredentials(boolean result) {
Log.i(TAG, "finishConfirmCredentials()");
final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE);
mAccountManager.setPassword(account, mPassword);
@@ -164,7 +176,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
}
/**
*
* Called when response is received from the server for authentication
* request. See onAuthenticationResult(). Sets the
* AccountAuthenticatorResult which is sent back to the caller. Also sets
@@ -172,26 +183,22 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
*
* @param the confirmCredentials result.
*/
private void finishLogin() {
protected void finishLogin() {
Log.i(TAG, "finishLogin()");
final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE);
if (mRequestNewAccount) {
mAccountManager.addAccountExplicitly(account, mPassword, null);
// Set contacts sync for this account.
ContentResolver.setSyncAutomatically(account,
ContactsContract.AUTHORITY, true);
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
} else {
mAccountManager.setPassword(account, mPassword);
}
final Intent intent = new Intent();
mAuthtoken = mPassword;
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mUsername);
intent
.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
if (mAuthtokenType != null
&& mAuthtokenType.equals(Constants.AUTHTOKEN_TYPE)) {
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
if (mAuthtokenType != null && mAuthtokenType.equals(Constants.AUTHTOKEN_TYPE)) {
intent.putExtra(AccountManager.KEY_AUTHTOKEN, mAuthtoken);
}
setAccountAuthenticatorResult(intent.getExtras());
@@ -202,7 +209,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
/**
* Hides the progress UI for a lengthy operation.
*/
protected void hideProgress() {
private void hideProgress() {
dismissDialog(0);
}
@@ -210,6 +217,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
* Called when the authentication process completes (see attemptLogin()).
*/
public void onAuthenticationResult(boolean result) {
Log.i(TAG, "onAuthenticationResult(" + result + ")");
// Hide the progress dialog
hideProgress();
@@ -223,14 +231,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
Log.e(TAG, "onAuthenticationResult: failed to authenticate");
if (mRequestNewAccount) {
// "Please enter a valid username/password.
mMessage
.setText(getText(R.string.login_activity_loginfail_text_both));
mMessage.setText(getText(R.string.login_activity_loginfail_text_both));
} else {
// "Please enter a valid password." (Used when the
// account is already in the database but the password
// doesn't work.)
mMessage
.setText(getText(R.string.login_activity_loginfail_text_pwonly));
mMessage.setText(getText(R.string.login_activity_loginfail_text_pwonly));
}
}
}
@@ -243,8 +249,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
if (TextUtils.isEmpty(mUsername)) {
// If no username, then we ask the user to log in using an
// appropriate service.
final CharSequence msg =
getText(R.string.login_activity_newaccount_text);
final CharSequence msg = getText(R.string.login_activity_newaccount_text);
return msg;
}
if (TextUtils.isEmpty(mPassword)) {
@@ -257,7 +262,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity {
/**
* Shows the progress UI for a lengthy operation.
*/
protected void showProgress() {
private void showProgress() {
showDialog(0);
}
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.client;
import android.accounts.Account;
@@ -52,21 +51,36 @@ import java.util.TimeZone;
/**
* Provides utility methods for communicating with the server.
*/
public class NetworkUtilities {
final public class NetworkUtilities {
/** The tag used to log to adb console. **/
private static final String TAG = "NetworkUtilities";
public static final String PARAM_USERNAME = "username";
/** The Intent extra to store password. **/
public static final String PARAM_PASSWORD = "password";
/** The Intent extra to store username. **/
public static final String PARAM_USERNAME = "username";
public static final String PARAM_UPDATED = "timestamp";
public static final String USER_AGENT = "AuthenticationService/1.0";
public static final int REGISTRATION_TIMEOUT = 30 * 1000; // ms
public static final String BASE_URL =
"https://samplesyncadapter.appspot.com";
public static final int REGISTRATION_TIMEOUT_MS = 30 * 1000; // ms
public static final String BASE_URL = "https://samplesyncadapter.appspot.com";
public static final String AUTH_URI = BASE_URL + "/auth";
public static final String FETCH_FRIEND_UPDATES_URI =
BASE_URL + "/fetch_friend_updates";
public static final String FETCH_FRIEND_UPDATES_URI = BASE_URL + "/fetch_friend_updates";
public static final String FETCH_STATUS_URI = BASE_URL + "/fetch_status";
private static HttpClient mHttpClient;
private NetworkUtilities() {
}
/**
* Configures the httpClient to connect to the URL provided.
*/
@@ -74,10 +88,9 @@ public class NetworkUtilities {
if (mHttpClient == null) {
mHttpClient = new DefaultHttpClient();
final HttpParams params = mHttpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params,
REGISTRATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, REGISTRATION_TIMEOUT);
ConnManagerParams.setTimeout(params, REGISTRATION_TIMEOUT);
HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT_M);
HttpConnectionParams.setSoTimeout(params, REGISTRATION_TIMEOUT_MS);
ConnManagerParams.setTimeout(params, REGISTRATION_TIMEOUT_MS);
}
}
@@ -94,7 +107,6 @@ public class NetworkUtilities {
try {
runnable.run();
} finally {
}
}
};
@@ -113,10 +125,10 @@ public class NetworkUtilities {
* @return boolean The boolean result indicating whether the user was
* successfully authenticated.
*/
public static boolean authenticate(String username, String password,
Handler handler, final Context context) {
final HttpResponse resp;
public static boolean authenticate(String username, String password, Handler handler,
final Context context) {
final HttpResponse resp;
final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(PARAM_USERNAME, username));
params.add(new BasicNameValuePair(PARAM_PASSWORD, password));
@@ -131,7 +143,6 @@ public class NetworkUtilities {
post.addHeader(entity.getContentType());
post.setEntity(entity);
maybeCreateHttpClient();
try {
resp = mHttpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
@@ -189,8 +200,9 @@ public class NetworkUtilities {
* @param context The caller Activity's context
* @return Thread The thread on which the network mOperations are executed.
*/
public static Thread attemptAuth(final String username,
final String password, final Handler handler, final Context context) {
public static Thread attemptAuth(final String username, final String password,
final Handler handler, final Context context) {
final Runnable runnable = new Runnable() {
public void run() {
authenticate(username, password, handler, context);
@@ -208,32 +220,27 @@ public class NetworkUtilities {
* @param lastUpdated The last time that sync was performed
* @return list The list of updates received from the server.
*/
public static List<User> fetchFriendUpdates(Account account,
String authtoken, Date lastUpdated) throws JSONException,
ParseException, IOException, AuthenticationException {
public static List<User> fetchFriendUpdates(Account account, String authtoken, Date lastUpdated)
throws JSONException, ParseException, IOException, AuthenticationException {
final ArrayList<User> friendList = new ArrayList<User>();
final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(PARAM_USERNAME, account.name));
params.add(new BasicNameValuePair(PARAM_PASSWORD, authtoken));
if (lastUpdated != null) {
final SimpleDateFormat formatter =
new SimpleDateFormat("yyyy/MM/dd HH:mm");
final SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
params.add(new BasicNameValuePair(PARAM_UPDATED, formatter
.format(lastUpdated)));
params.add(new BasicNameValuePair(PARAM_UPDATED, formatter.format(lastUpdated)));
}
Log.i(TAG, params.toString());
HttpEntity entity = null;
entity = new UrlEncodedFormEntity(params);
final HttpPost post = new HttpPost(FETCH_FRIEND_UPDATES_URI);
post.addHeader(entity.getContentType());
post.setEntity(entity);
maybeCreateHttpClient();
final HttpResponse resp = mHttpClient.execute(post);
final String response = EntityUtils.toString(resp.getEntity());
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// Succesfully connected to the samplesyncadapter server and
// authenticated.
@@ -245,12 +252,10 @@ public class NetworkUtilities {
}
} else {
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
Log.e(TAG,
"Authentication exception in fetching remote contacts");
Log.e(TAG, "Authentication exception in fetching remote contacts");
throw new AuthenticationException();
} else {
Log.e(TAG, "Server error in fetching remote contacts: "
+ resp.getStatusLine());
Log.e(TAG, "Server error in fetching remote contacts: " + resp.getStatusLine());
throw new IOException();
}
}
@@ -265,24 +270,21 @@ public class NetworkUtilities {
* account
* @return list The list of status messages received from the server.
*/
public static List<User.Status> fetchFriendStatuses(Account account,
String authtoken) throws JSONException, ParseException, IOException,
AuthenticationException {
public static List<User.Status> fetchFriendStatuses(Account account, String authtoken)
throws JSONException, ParseException, IOException, AuthenticationException {
final ArrayList<User.Status> statusList = new ArrayList<User.Status>();
final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(PARAM_USERNAME, account.name));
params.add(new BasicNameValuePair(PARAM_PASSWORD, authtoken));
HttpEntity entity = null;
entity = new UrlEncodedFormEntity(params);
final HttpPost post = new HttpPost(FETCH_STATUS_URI);
post.addHeader(entity.getContentType());
post.setEntity(entity);
maybeCreateHttpClient();
final HttpResponse resp = mHttpClient.execute(post);
final String response = EntityUtils.toString(resp.getEntity());
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// Succesfully connected to the samplesyncadapter server and
// authenticated.
@@ -293,8 +295,7 @@ public class NetworkUtilities {
}
} else {
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
Log.e(TAG,
"Authentication exception in fetching friend status list");
Log.e(TAG, "Authentication exception in fetching friend status list");
throw new AuthenticationException();
} else {
Log.e(TAG, "Server error in fetching friend status list");
@@ -303,5 +304,4 @@ public class NetworkUtilities {
}
return statusList;
}
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.client;
import android.util.Log;
@@ -23,16 +22,24 @@ import org.json.JSONObject;
/**
* Represents a sample SyncAdapter user
*/
public class User {
final public class User {
private final String mUserName;
private final String mFirstName;
private final String mLastName;
private final String mCellPhone;
private final String mOfficePhone;
private final String mHomePhone;
private final String mEmail;
private final boolean mDeleted;
private final int mUserId;
public int getUserId() {
@@ -71,9 +78,9 @@ public class User {
return mDeleted;
}
public User(String name, String firstName, String lastName,
String cellPhone, String officePhone, String homePhone, String email,
Boolean deleted, Integer userId) {
private User(String name, String firstName, String lastName, String cellPhone,
String officePhone, String homePhone, String email, Boolean deleted, Integer userId) {
mUserName = name;
mFirstName = firstName;
mLastName = lastName;
@@ -92,34 +99,33 @@ public class User {
* @return user The new instance of Voiper user created from the JSON data.
*/
public static User valueOf(JSONObject user) {
try {
final String userName = user.getString("u");
final String firstName = user.has("f") ? user.getString("f") : null;
final String lastName = user.has("l") ? user.getString("l") : null;
final String cellPhone = user.has("m") ? user.getString("m") : null;
final String officePhone =
user.has("o") ? user.getString("o") : null;
final String officePhone = user.has("o") ? user.getString("o") : null;
final String homePhone = user.has("h") ? user.getString("h") : null;
final String email = user.has("e") ? user.getString("e") : null;
final boolean deleted =
user.has("d") ? user.getBoolean("d") : false;
final boolean deleted = user.has("d") ? user.getBoolean("d") : false;
final int userId = user.getInt("i");
return new User(userName, firstName, lastName, cellPhone,
officePhone, homePhone, email, deleted, userId);
return new User(userName, firstName, lastName, cellPhone, officePhone, homePhone,
email, deleted, userId);
} catch (final Exception ex) {
Log.i("User", "Error parsing JSON user object" + ex.toString());
}
return null;
}
/**
* Represents the User's status messages
*
*/
public static class Status {
final public static class Status {
private final Integer mUserId;
private final String mStatus;
public int getUserId() {
@@ -146,5 +152,4 @@ public class User {
return null;
}
}
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.platform;
import android.content.ContentProviderOperation;
@@ -29,12 +28,14 @@ import java.util.ArrayList;
/**
* This class handles execution of batch mOperations on Contacts provider.
*/
public class BatchOperation {
final public class BatchOperation {
private final String TAG = "BatchOperation";
private final ContentResolver mResolver;
// List for storing the batch mOperations
ArrayList<ContentProviderOperation> mOperations;
private final ArrayList<ContentProviderOperation> mOperations;
public BatchOperation(Context context, ContentResolver resolver) {
mResolver = resolver;
@@ -50,6 +51,7 @@ public class BatchOperation {
}
public void execute() {
if (mOperations.size() == 0) {
return;
}
@@ -63,5 +65,4 @@ public class BatchOperation {
}
mOperations.clear();
}
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.platform;
import android.content.ContentResolver;
@@ -41,10 +40,12 @@ import java.util.List;
* Class for managing contacts sync related mOperations
*/
public class ContactManager {
/**
* Custom IM protocol used when storing status messages.
*/
public static final String CUSTOM_IM_PROTOCOL = "SampleSyncAdapter";
private static final String TAG = "ContactManager";
/**
@@ -54,13 +55,12 @@ public class ContactManager {
* @param account The username for the account
* @param users The list of users
*/
public static synchronized void syncContacts(Context context,
String account, List<User> users) {
public static synchronized void syncContacts(Context context, String account, List<User> users) {
long userId;
long rawContactId = 0;
final ContentResolver resolver = context.getContentResolver();
final BatchOperation batchOperation =
new BatchOperation(context, resolver);
final BatchOperation batchOperation = new BatchOperation(context, resolver);
Log.d(TAG, "In SyncContacts");
for (final User user : users) {
userId = user.getUserId();
@@ -69,8 +69,7 @@ public class ContactManager {
if (rawContactId != 0) {
if (!user.isDeleted()) {
// update contact
updateContact(context, resolver, account, user,
rawContactId, batchOperation);
updateContact(context, resolver, account, user, rawContactId, batchOperation);
} else {
// delete contact
deleteContact(context, rawContactId, batchOperation);
@@ -98,17 +97,15 @@ public class ContactManager {
* @param accountName the username of the logged in user
* @param statuses the list of statuses to store
*/
public static void insertStatuses(Context context, String username,
List<User.Status> list) {
public static void insertStatuses(Context context, String username, List<User.Status> list) {
final ContentValues values = new ContentValues();
final ContentResolver resolver = context.getContentResolver();
final BatchOperation batchOperation =
new BatchOperation(context, resolver);
final BatchOperation batchOperation = new BatchOperation(context, resolver);
for (final User.Status status : list) {
// Look up the user's sample SyncAdapter data row
final long userId = status.getUserId();
final long profileId = lookupProfile(resolver, userId);
// Insert the activity into the stream
if (profileId > 0) {
values.put(StatusUpdates.DATA_ID, profileId);
@@ -117,15 +114,11 @@ public class ContactManager {
values.put(StatusUpdates.CUSTOM_PROTOCOL, CUSTOM_IM_PROTOCOL);
values.put(StatusUpdates.IM_ACCOUNT, username);
values.put(StatusUpdates.IM_HANDLE, status.getUserId());
values.put(StatusUpdates.STATUS_RES_PACKAGE, context
.getPackageName());
values.put(StatusUpdates.STATUS_RES_PACKAGE, context.getPackageName());
values.put(StatusUpdates.STATUS_ICON, R.drawable.icon);
values.put(StatusUpdates.STATUS_LABEL, R.string.label);
batchOperation
.add(ContactOperations.newInsertCpo(
StatusUpdates.CONTENT_URI, true).withValues(values)
.build());
batchOperation.add(ContactOperations.newInsertCpo(StatusUpdates.CONTENT_URI, true)
.withValues(values).build());
// A sync adapter should batch operations on multiple contacts,
// because it will make a dramatic performance difference.
if (batchOperation.size() >= 50) {
@@ -143,16 +136,16 @@ public class ContactManager {
* @param accountName the account the contact belongs to
* @param user the sample SyncAdapter User object
*/
private static void addContact(Context context, String accountName,
User user, BatchOperation batchOperation) {
private static void addContact(Context context, String accountName, User user,
BatchOperation batchOperation) {
// Put the data in the contacts provider
final ContactOperations contactOp =
ContactOperations.createNewContact(context, user.getUserId(),
accountName, batchOperation);
contactOp.addName(user.getFirstName(), user.getLastName()).addEmail(
user.getEmail()).addPhone(user.getCellPhone(), Phone.TYPE_MOBILE)
.addPhone(user.getHomePhone(), Phone.TYPE_OTHER).addProfileAction(
user.getUserId());
ContactOperations.createNewContact(context, user.getUserId(), accountName,
batchOperation);
contactOp.addName(user.getFirstName(), user.getLastName()).addEmail(user.getEmail())
.addPhone(user.getCellPhone(), Phone.TYPE_MOBILE).addPhone(user.getHomePhone(),
Phone.TYPE_OTHER).addProfileAction(user.getUserId());
}
/**
@@ -165,76 +158,57 @@ public class ContactManager {
* @param rawContactId the unique Id for this rawContact in contacts
* provider
*/
private static void updateContact(Context context,
ContentResolver resolver, String accountName, User user,
long rawContactId, BatchOperation batchOperation) {
private static void updateContact(Context context, ContentResolver resolver,
String accountName, User user, long rawContactId, BatchOperation batchOperation) {
Uri uri;
String cellPhone = null;
String otherPhone = null;
String email = null;
final Cursor c =
resolver.query(Data.CONTENT_URI, DataQuery.PROJECTION,
DataQuery.SELECTION,
resolver.query(Data.CONTENT_URI, DataQuery.PROJECTION, DataQuery.SELECTION,
new String[] {String.valueOf(rawContactId)}, null);
final ContactOperations contactOp =
ContactOperations.updateExistingContact(context, rawContactId,
batchOperation);
ContactOperations.updateExistingContact(context, rawContactId, batchOperation);
try {
while (c.moveToNext()) {
final long id = c.getLong(DataQuery.COLUMN_ID);
final String mimeType = c.getString(DataQuery.COLUMN_MIMETYPE);
uri = ContentUris.withAppendedId(Data.CONTENT_URI, id);
if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) {
final String lastName =
c.getString(DataQuery.COLUMN_FAMILY_NAME);
final String firstName =
c.getString(DataQuery.COLUMN_GIVEN_NAME);
contactOp.updateName(uri, firstName, lastName, user
.getFirstName(), user.getLastName());
}
else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
final String lastName = c.getString(DataQuery.COLUMN_FAMILY_NAME);
final String firstName = c.getString(DataQuery.COLUMN_GIVEN_NAME);
contactOp.updateName(uri, firstName, lastName, user.getFirstName(), user
.getLastName());
} else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
final int type = c.getInt(DataQuery.COLUMN_PHONE_TYPE);
if (type == Phone.TYPE_MOBILE) {
cellPhone = c.getString(DataQuery.COLUMN_PHONE_NUMBER);
contactOp.updatePhone(cellPhone, user.getCellPhone(),
uri);
contactOp.updatePhone(cellPhone, user.getCellPhone(), uri);
} else if (type == Phone.TYPE_OTHER) {
otherPhone = c.getString(DataQuery.COLUMN_PHONE_NUMBER);
contactOp.updatePhone(otherPhone, user.getHomePhone(),
uri);
contactOp.updatePhone(otherPhone, user.getHomePhone(), uri);
}
}
else if (Data.MIMETYPE.equals(Email.CONTENT_ITEM_TYPE)) {
} else if (Data.MIMETYPE.equals(Email.CONTENT_ITEM_TYPE)) {
email = c.getString(DataQuery.COLUMN_EMAIL_ADDRESS);
contactOp.updateEmail(user.getEmail(), email, uri);
}
} // while
} finally {
c.close();
}
// Add the cell phone, if present and not updated above
if (cellPhone == null) {
contactOp.addPhone(user.getCellPhone(), Phone.TYPE_MOBILE);
}
// Add the other phone, if present and not updated above
if (otherPhone == null) {
contactOp.addPhone(user.getHomePhone(), Phone.TYPE_OTHER);
}
// Add the email address, if present and not updated above
if (email == null) {
contactOp.addEmail(user.getEmail());
}
}
/**
@@ -246,9 +220,9 @@ public class ContactManager {
*/
private static void deleteContact(Context context, long rawContactId,
BatchOperation batchOperation) {
batchOperation.add(ContactOperations.newDeleteCpo(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
true).build());
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId), true).build());
}
/**
@@ -260,11 +234,11 @@ public class ContactManager {
* @return the RawContact id, or 0 if not found
*/
private static long lookupRawContact(ContentResolver resolver, long userId) {
long authorId = 0;
final Cursor c =
resolver.query(RawContacts.CONTENT_URI, UserIdQuery.PROJECTION,
UserIdQuery.SELECTION, new String[] {String.valueOf(userId)},
null);
resolver.query(RawContacts.CONTENT_URI, UserIdQuery.PROJECTION, UserIdQuery.SELECTION,
new String[] {String.valueOf(userId)}, null);
try {
if (c.moveToFirst()) {
authorId = c.getLong(UserIdQuery.COLUMN_ID);
@@ -286,11 +260,11 @@ public class ContactManager {
* @return the profile Data row id, or 0 if not found
*/
private static long lookupProfile(ContentResolver resolver, long userId) {
long profileId = 0;
final Cursor c =
resolver.query(Data.CONTENT_URI, ProfileQuery.PROJECTION,
ProfileQuery.SELECTION, new String[] {String.valueOf(userId)},
null);
resolver.query(Data.CONTENT_URI, ProfileQuery.PROJECTION, ProfileQuery.SELECTION,
new String[] {String.valueOf(userId)}, null);
try {
if (c != null && c.moveToFirst()) {
profileId = c.getLong(ProfileQuery.COLUMN_ID);
@@ -307,22 +281,30 @@ public class ContactManager {
* Constants for a query to find a contact given a sample SyncAdapter user
* ID.
*/
private interface ProfileQuery {
final private static class ProfileQuery {
private ProfileQuery() {
}
public final static String[] PROJECTION = new String[] {Data._ID};
public final static int COLUMN_ID = 0;
public static final String SELECTION =
Data.MIMETYPE + "='" + SampleSyncAdapterColumns.MIME_PROFILE
+ "' AND " + SampleSyncAdapterColumns.DATA_PID + "=?";
Data.MIMETYPE + "='" + SampleSyncAdapterColumns.MIME_PROFILE + "' AND "
+ SampleSyncAdapterColumns.DATA_PID + "=?";
}
/**
* Constants for a query to find a contact given a sample SyncAdapter user
* ID.
*/
private interface UserIdQuery {
public final static String[] PROJECTION =
new String[] {RawContacts._ID};
final private static class UserIdQuery {
private UserIdQuery() {
}
public final static String[] PROJECTION = new String[] {RawContacts._ID};
public final static int COLUMN_ID = 0;
@@ -334,21 +316,34 @@ public class ContactManager {
/**
* Constants for a query to get contact data for a given rawContactId
*/
private interface DataQuery {
final private static class DataQuery {
private DataQuery() {
}
public static final String[] PROJECTION =
new String[] {Data._ID, Data.MIMETYPE, Data.DATA1, Data.DATA2,
Data.DATA3,};
new String[] {Data._ID, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3,};
public static final int COLUMN_ID = 0;
public static final int COLUMN_MIMETYPE = 1;
public static final int COLUMN_DATA1 = 2;
public static final int COLUMN_DATA2 = 3;
public static final int COLUMN_DATA3 = 4;
public static final int COLUMN_PHONE_NUMBER = COLUMN_DATA1;
public static final int COLUMN_PHONE_TYPE = COLUMN_DATA2;
public static final int COLUMN_EMAIL_ADDRESS = COLUMN_DATA1;
public static final int COLUMN_EMAIL_TYPE = COLUMN_DATA2;
public static final int COLUMN_GIVEN_NAME = COLUMN_DATA2;
public static final int COLUMN_FAMILY_NAME = COLUMN_DATA3;
public static final String SELECTION = Data.RAW_CONTACT_ID + "=?";

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.platform;
import android.content.ContentProviderOperation;
@@ -38,12 +37,19 @@ import com.example.android.samplesync.R;
public class ContactOperations {
private final ContentValues mValues;
private ContentProviderOperation.Builder mBuilder;
private final BatchOperation mBatchOperation;
private final Context mContext;
private boolean mYield;
private long mRawContactId;
private int mBackReference;
private boolean mIsNewContact;
/**
@@ -55,10 +61,10 @@ public class ContactOperations {
* @param accountName the username of the current login
* @return instance of ContactOperations
*/
public static ContactOperations createNewContact(Context context,
int userId, String accountName, BatchOperation batchOperation) {
return new ContactOperations(context, userId, accountName,
batchOperation);
public static ContactOperations createNewContact(Context context, int userId,
String accountName, BatchOperation batchOperation) {
return new ContactOperations(context, userId, accountName, batchOperation);
}
/**
@@ -69,8 +75,9 @@ public class ContactOperations {
* @param rawContactId the unique Id of the existing rawContact
* @return instance of ContactOperations
*/
public static ContactOperations updateExistingContact(Context context,
long rawContactId, BatchOperation batchOperation) {
public static ContactOperations updateExistingContact(Context context, long rawContactId,
BatchOperation batchOperation) {
return new ContactOperations(context, rawContactId, batchOperation);
}
@@ -83,19 +90,18 @@ public class ContactOperations {
public ContactOperations(Context context, int userId, String accountName,
BatchOperation batchOperation) {
this(context, batchOperation);
mBackReference = mBatchOperation.size();
mIsNewContact = true;
mValues.put(RawContacts.SOURCE_ID, userId);
mValues.put(RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
mValues.put(RawContacts.ACCOUNT_NAME, accountName);
mBuilder =
newInsertCpo(RawContacts.CONTENT_URI, true).withValues(mValues);
mBuilder = newInsertCpo(RawContacts.CONTENT_URI, true).withValues(mValues);
mBatchOperation.add(mBuilder.build());
}
public ContactOperations(Context context, long rawContactId,
BatchOperation batchOperation) {
public ContactOperations(Context context, long rawContactId, BatchOperation batchOperation) {
this(context, batchOperation);
mIsNewContact = false;
mRawContactId = rawContactId;
@@ -109,16 +115,15 @@ public class ContactOperations {
* @return instance of ContactOperations
*/
public ContactOperations addName(String firstName, String lastName) {
mValues.clear();
if (!TextUtils.isEmpty(firstName)) {
mValues.put(StructuredName.GIVEN_NAME, firstName);
mValues.put(StructuredName.MIMETYPE,
StructuredName.CONTENT_ITEM_TYPE);
mValues.put(StructuredName.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
}
if (!TextUtils.isEmpty(lastName)) {
mValues.put(StructuredName.FAMILY_NAME, lastName);
mValues.put(StructuredName.MIMETYPE,
StructuredName.CONTENT_ITEM_TYPE);
mValues.put(StructuredName.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
}
if (mValues.size() > 0) {
addInsertOp();
@@ -188,8 +193,7 @@ public class ContactOperations {
* @param uri Uri for the existing raw contact to be updated
* @return instance of ContactOperations
*/
public ContactOperations updateEmail(String email, String existingEmail,
Uri uri) {
public ContactOperations updateEmail(String email, String existingEmail, Uri uri) {
if (!TextUtils.equals(existingEmail, email)) {
mValues.clear();
mValues.put(Email.DATA, email);
@@ -207,10 +211,11 @@ public class ContactOperations {
* @param uri Uri for the existing raw contact to be updated
* @return instance of ContactOperations
*/
public ContactOperations updateName(Uri uri, String existingFirstName,
String existingLastName, String firstName, String lastName) {
Log.i("ContactOperations", "ef=" + existingFirstName + "el="
+ existingLastName + "f=" + firstName + "l=" + lastName);
public ContactOperations updateName(Uri uri, String existingFirstName, String existingLastName,
String firstName, String lastName) {
Log.i("ContactOperations", "ef=" + existingFirstName + "el=" + existingLastName + "f="
+ firstName + "l=" + lastName);
mValues.clear();
if (!TextUtils.equals(existingFirstName, firstName)) {
mValues.put(StructuredName.GIVEN_NAME, firstName);
@@ -232,8 +237,7 @@ public class ContactOperations {
* @param uri Uri for the existing raw contact to be updated
* @return instance of ContactOperations
*/
public ContactOperations updatePhone(String existingNumber, String phone,
Uri uri) {
public ContactOperations updatePhone(String existingNumber, String phone, Uri uri) {
if (!TextUtils.equals(phone, existingNumber)) {
mValues.clear();
mValues.put(Phone.NUMBER, phone);
@@ -260,16 +264,14 @@ public class ContactOperations {
* Adds an insert operation into the batch
*/
private void addInsertOp() {
if (!mIsNewContact) {
mValues.put(Phone.RAW_CONTACT_ID, mRawContactId);
}
mBuilder =
newInsertCpo(addCallerIsSyncAdapterParameter(Data.CONTENT_URI),
mYield);
mBuilder = newInsertCpo(addCallerIsSyncAdapterParameter(Data.CONTENT_URI), mYield);
mBuilder.withValues(mValues);
if (mIsNewContact) {
mBuilder
.withValueBackReference(Data.RAW_CONTACT_ID, mBackReference);
mBuilder.withValueBackReference(Data.RAW_CONTACT_ID, mBackReference);
}
mYield = false;
mBatchOperation.add(mBuilder.build());
@@ -284,28 +286,23 @@ public class ContactOperations {
mBatchOperation.add(mBuilder.build());
}
public static ContentProviderOperation.Builder newInsertCpo(Uri uri,
boolean yield) {
return ContentProviderOperation.newInsert(
addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield);
public static ContentProviderOperation.Builder newInsertCpo(Uri uri, boolean yield) {
return ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(uri))
.withYieldAllowed(yield);
}
public static ContentProviderOperation.Builder newUpdateCpo(Uri uri,
boolean yield) {
return ContentProviderOperation.newUpdate(
addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield);
public static ContentProviderOperation.Builder newUpdateCpo(Uri uri, boolean yield) {
return ContentProviderOperation.newUpdate(addCallerIsSyncAdapterParameter(uri))
.withYieldAllowed(yield);
}
public static ContentProviderOperation.Builder newDeleteCpo(Uri uri,
boolean yield) {
return ContentProviderOperation.newDelete(
addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield);
public static ContentProviderOperation.Builder newDeleteCpo(Uri uri, boolean yield) {
return ContentProviderOperation.newDelete(addCallerIsSyncAdapterParameter(uri))
.withYieldAllowed(yield);
}
private static Uri addCallerIsSyncAdapterParameter(Uri uri) {
return uri.buildUpon().appendQueryParameter(
ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
return uri.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.build();
}
}

View File

@@ -20,7 +20,11 @@ import android.provider.ContactsContract.Data;
/*
* The standard columns representing contact's info from social apps.
*/
public interface SampleSyncAdapterColumns {
public final class SampleSyncAdapterColumns {
private SampleSyncAdapterColumns() {
}
/**
* MIME-type used when storing a profile {@link Data} entry.
*/
@@ -28,7 +32,8 @@ public interface SampleSyncAdapterColumns {
"vnd.android.cursor.item/vnd.samplesyncadapter.profile";
public static final String DATA_PID = Data.DATA1;
public static final String DATA_SUMMARY = Data.DATA2;
public static final String DATA_DETAIL = Data.DATA3;
public static final String DATA_SUMMARY = Data.DATA2;
public static final String DATA_DETAIL = Data.DATA3;
}

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.syncadapter;
import android.accounts.Account;
@@ -46,9 +45,11 @@ import java.util.List;
* platform ContactOperations provider.
*/
public class SyncAdapter extends AbstractThreadedSyncAdapter {
private static final String TAG = "SyncAdapter";
private final AccountManager mAccountManager;
private final Context mContext;
private Date mLastUpdated;
@@ -62,18 +63,17 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
List<User> users;
List<Status> statuses;
String authtoken = null;
try {
// use the account manager to request the credentials
authtoken =
mAccountManager.blockingGetAuthToken(account,
Constants.AUTHTOKEN_TYPE, true /* notifyAuthFailure */);
// fetch updates from the sample service over the cloud
users =
NetworkUtilities.fetchFriendUpdates(account, authtoken,
mLastUpdated);
try {
// use the account manager to request the credentials
authtoken =
mAccountManager
.blockingGetAuthToken(account, Constants.AUTHTOKEN_TYPE, true /* notifyAuthFailure */);
// fetch updates from the sample service over the cloud
users = NetworkUtilities.fetchFriendUpdates(account, authtoken, mLastUpdated);
// update the last synced date.
mLastUpdated = new Date();
// update platform contacts.
@@ -91,8 +91,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
Log.e(TAG, "IOException", e);
syncResult.stats.numIoExceptions++;
} catch (final AuthenticationException e) {
mAccountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE,
authtoken);
mAccountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE, authtoken);
syncResult.stats.numAuthExceptions++;
Log.e(TAG, "AuthenticationException", e);
} catch (final ParseException e) {

View File

@@ -13,7 +13,6 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.example.android.samplesync.syncadapter;
import android.app.Service;
@@ -26,12 +25,11 @@ import android.os.IBinder;
* IBinder.
*/
public class SyncService extends Service {
private static final Object sSyncAdapterLock = new Object();
private static SyncAdapter sSyncAdapter = null;
/*
* {@inheritDoc}
*/
@Override
public void onCreate() {
synchronized (sSyncAdapterLock) {
@@ -41,9 +39,6 @@ public class SyncService extends Service {
}
}
/*
* {@inheritDoc}
*/
@Override
public IBinder onBind(Intent intent) {
return sSyncAdapter.getSyncAdapterBinder();