List of usage examples for android.net Uri buildUpon
public abstract Builder buildUpon();
From source file:com.dwdesign.tweetings.util.Utils.java
public static Uri buildQueryUri(final Uri uri, final boolean notify) { if (uri == null) return null; final Uri.Builder uribuilder = uri.buildUpon(); uribuilder.appendQueryParameter(QUERY_PARAM_NOTIFY, String.valueOf(notify)); return uribuilder.build(); }
From source file:com.android.mail.browse.ConversationCursor.java
private UnderlyingCursorWrapper doQuery(boolean withLimit) { Uri uri = qUri; if (withLimit) { uri = uri.buildUpon().appendQueryParameter(ConversationListQueryParameters.LIMIT, ConversationListQueryParameters.DEFAULT_LIMIT).build(); }//from ww w . j a v a 2s . com long time = System.currentTimeMillis(); Utils.traceBeginSection("query"); final Cursor result = mResolver.query(uri, qProjection, null, null, null); Utils.traceEndSection(); if (result == null) { LogUtils.w(LOG_TAG, "doQuery returning null cursor, uri: " + uri); } else if (DEBUG) { time = System.currentTimeMillis() - time; LogUtils.i(LOG_TAG, "ConversationCursor query: %s, %dms, %d results", uri, time, result.getCount()); } System.gc(); return new UnderlyingCursorWrapper(result, mCachingEnabled); }
From source file:edu.mit.mobile.android.locast.sync.SyncEngine.java
/** * @param toSync// w w w . j ava 2s .com * @param account * @param extras * @param provider * @param syncResult * @return true if the item was sync'd successfully. Soft errors will cause this to return * false. * @throws RemoteException * @throws SyncException * @throws JSONException * @throws IOException * @throws NetworkProtocolException * @throws NoPublicPath * @throws OperationApplicationException * @throws InterruptedException */ public boolean sync(Uri toSync, Account account, Bundle extras, ContentProviderClient provider, SyncResult syncResult) throws RemoteException, SyncException, JSONException, IOException, NetworkProtocolException, NoPublicPath, OperationApplicationException, InterruptedException { String pubPath = null; // // Handle http or https uris separately. These require the // destination uri. // if ("http".equals(toSync.getScheme()) || "https".equals(toSync.getScheme())) { pubPath = toSync.toString(); if (!extras.containsKey(EXTRA_DESTINATION_URI)) { throw new IllegalArgumentException("missing EXTRA_DESTINATION_URI when syncing HTTP URIs"); } toSync = Uri.parse(extras.getString(EXTRA_DESTINATION_URI)); } final String type = provider.getType(toSync); final boolean isDir = type.startsWith(CONTENT_TYPE_PREFIX_DIR); final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false); // skip any items already sync'd if (!manualSync && mLastUpdated.isUpdatedRecently(toSync)) { if (DEBUG) { Log.d(TAG, "not syncing " + toSync + " as it's been updated recently"); } syncResult.stats.numSkippedEntries++; return false; } // the sync map will convert the json data to ContentValues final SyncMap syncMap = MediaProvider.getSyncMap(provider, toSync); final Uri toSyncWithoutQuerystring = toSync.buildUpon().query(null).build(); final HashMap<String, SyncStatus> syncStatuses = new HashMap<String, SyncEngine.SyncStatus>(); final ArrayList<ContentProviderOperation> cpo = new ArrayList<ContentProviderOperation>(); final LinkedList<String> cpoPubUris = new LinkedList<String>(); // // first things first, upload any content that needs to be // uploaded. // try { uploadUnpublished(toSync, account, provider, syncMap, syncStatuses, syncResult); if (Thread.interrupted()) { throw new InterruptedException(); } // this should ensure that all items have a pubPath when we // query it below. if (pubPath == null) { // we should avoid calling this too much as it // can be expensive pubPath = MediaProvider.getPublicPath(mContext, toSync); } } catch (final NoPublicPath e) { // TODO this is a special case and this is probably not the best place to handle this. // Ideally, this should be done in such a way as to reduce any extra DB queries - // perhaps by doing a join with the parent. if (syncMap.isFlagSet(SyncMap.FLAG_PARENT_MUST_SYNC_FIRST)) { if (DEBUG) { Log.d(TAG, "skipping " + toSync + " whose parent hasn't been sync'd first"); } syncResult.stats.numSkippedEntries++; return false; } // if it's an item, we can handle it. if (isDir) { throw e; } } if (pubPath == null) { // this should have been updated already by the initial // upload, so something must be wrong throw new SyncException("never got a public path for " + toSync); } if (DEBUG) { Log.d(TAG, "sync(toSync=" + toSync + ", account=" + account + ", extras=" + extras + ", manualSync=" + manualSync + ",...)"); Log.d(TAG, "pubPath: " + pubPath); } final long request_time = System.currentTimeMillis(); HttpResponse hr = mNetworkClient.get(pubPath); final long response_time = System.currentTimeMillis(); // the time compensation below allows a time-based synchronization to function even if the // local clock is entirely wrong. The server's time is extracted using the Date header and // all are compared relative to the respective clock reference. Any data that's stored on // the mobile should be stored relative to the local clock and the server will respect the // same. long serverTime; try { serverTime = getServerTime(hr); } catch (final DateParseException e) { Log.w(TAG, "could not retrieve date from server. Using local time, which may be incorrect.", e); serverTime = System.currentTimeMillis(); } // TODO check out // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html final long response_delay = response_time - request_time; if (DEBUG) { Log.d(TAG, "request took " + response_delay + "ms"); } final long localTime = request_time; // add this to the server time to get the local time final long localOffset = (localTime - serverTime); if (Math.abs(localOffset) > 30 * 60 * 1000) { Log.w(TAG, "local clock is off by " + localOffset + "ms"); } if (Thread.interrupted()) { throw new InterruptedException(); } final HttpEntity ent = hr.getEntity(); String selection; String selectionInverse; String[] selectionArgs; if (isDir) { final JSONArray ja = new JSONArray(StreamUtils.inputStreamToString(ent.getContent())); ent.consumeContent(); final int len = ja.length(); selectionArgs = new String[len]; // build the query to see which items are already in the // database final StringBuilder sb = new StringBuilder(); sb.append("("); for (int i = 0; i < len; i++) { if (Thread.interrupted()) { throw new InterruptedException(); } final SyncStatus syncStatus = loadItemFromJsonObject(ja.getJSONObject(i), syncMap, serverTime); syncStatuses.put(syncStatus.remote, syncStatus); selectionArgs[i] = syncStatus.remote; // add in a placeholder for the query sb.append('?'); if (i != (len - 1)) { sb.append(','); } } sb.append(")"); final String placeholders = sb.toString(); selection = JsonSyncableItem._PUBLIC_URI + " IN " + placeholders; selectionInverse = JsonSyncableItem._PUBLIC_URI + " NOT IN " + placeholders; } else { final JSONObject jo = new JSONObject(StreamUtils.inputStreamToString(ent.getContent())); ent.consumeContent(); final SyncStatus syncStatus = loadItemFromJsonObject(jo, syncMap, serverTime); syncStatuses.put(syncStatus.remote, syncStatus); selection = JsonSyncableItem._PUBLIC_URI + "=?"; selectionInverse = JsonSyncableItem._PUBLIC_URI + "!=?"; selectionArgs = new String[] { syncStatus.remote }; } // first check without the querystring. This will ensure that we // properly mark things that we already have in the database. final Cursor check = provider.query(toSyncWithoutQuerystring, SYNC_PROJECTION, selection, selectionArgs, null); // these items are on both sides try { final int pubUriCol = check.getColumnIndex(JsonSyncableItem._PUBLIC_URI); final int idCol = check.getColumnIndex(JsonSyncableItem._ID); // All the items in this cursor should be found on both // the client and the server. for (check.moveToFirst(); !check.isAfterLast(); check.moveToNext()) { if (Thread.interrupted()) { throw new InterruptedException(); } final long id = check.getLong(idCol); final Uri localUri = ContentUris.withAppendedId(toSync, id); final String pubUri = check.getString(pubUriCol); final SyncStatus itemStatus = syncStatuses.get(pubUri); itemStatus.state = SyncState.BOTH_UNKNOWN; itemStatus.local = localUri; // make the status searchable by both remote and // local uri syncStatuses.put(localUri.toString(), itemStatus); } } finally { check.close(); } Cursor c = provider.query(toSync, SYNC_PROJECTION, selection, selectionArgs, null); // these items are on both sides try { final int pubUriCol = c.getColumnIndex(JsonSyncableItem._PUBLIC_URI); final int localModifiedCol = c.getColumnIndex(JsonSyncableItem._MODIFIED_DATE); final int serverModifiedCol = c.getColumnIndex(JsonSyncableItem._SERVER_MODIFIED_DATE); final int idCol = c.getColumnIndex(JsonSyncableItem._ID); // All the items in this cursor should be found on both // the client and the server. for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { if (Thread.interrupted()) { throw new InterruptedException(); } final long id = c.getLong(idCol); final Uri localUri = ContentUris.withAppendedId(toSync, id); final String pubUri = c.getString(pubUriCol); final SyncStatus itemStatus = syncStatuses.get(pubUri); if (itemStatus.state == SyncState.ALREADY_UP_TO_DATE || itemStatus.state == SyncState.NOW_UP_TO_DATE) { if (DEBUG) { Log.d(TAG, localUri + "(" + pubUri + ")" + " is already up to date."); } continue; } itemStatus.local = localUri; // make the status searchable by both remote and local uri syncStatuses.put(localUri.toString(), itemStatus); // last modified as stored in the DB, in phone time final long itemLocalModified = c.getLong(localModifiedCol); // last modified as stored in the DB, in server time final long itemServerModified = c.getLong(serverModifiedCol); final long localAge = localTime - itemLocalModified; final long remoteAge = serverTime - itemStatus.remoteModifiedTime; final long ageDifference = Math.abs(localAge - remoteAge); // up to date, as far remote -> local goes if (itemServerModified == itemStatus.remoteModifiedTime) { itemStatus.state = SyncState.ALREADY_UP_TO_DATE; if (DEBUG) { Log.d(TAG, pubUri + " is up to date."); } // need to download } else if (localAge > remoteAge) { if (DEBUG) { final long serverModified = itemStatus.remoteModifiedTime; Log.d(TAG, pubUri + " : local is " + ageDifference + "ms older (" + android.text.format.DateUtils.formatDateTime(mContext, itemLocalModified, FORMAT_ARGS_DEBUG) + ") than remote (" + android.text.format.DateUtils.formatDateTime(mContext, serverModified, FORMAT_ARGS_DEBUG) + "); updating local copy..."); } itemStatus.state = SyncState.REMOTE_DIRTY; final ContentProviderOperation.Builder b = ContentProviderOperation.newUpdate(localUri); // update this so it's in the local timescale correctServerOffset(itemStatus.remoteCVs, JsonSyncableItem._CREATED_DATE, JsonSyncableItem._CREATED_DATE, localOffset); correctServerOffset(itemStatus.remoteCVs, JsonSyncableItem._SERVER_MODIFIED_DATE, JsonSyncableItem._MODIFIED_DATE, localOffset); b.withValues(itemStatus.remoteCVs); b.withExpectedCount(1); cpo.add(b.build()); cpoPubUris.add(pubUri); syncResult.stats.numUpdates++; // need to upload } else if (localAge < remoteAge) { if (DEBUG) { final long serverModified = itemStatus.remoteModifiedTime; Log.d(TAG, pubUri + " : local is " + ageDifference + "ms newer (" + android.text.format.DateUtils.formatDateTime(mContext, itemLocalModified, FORMAT_ARGS_DEBUG) + ") than remote (" + android.text.format.DateUtils.formatDateTime(mContext, serverModified, FORMAT_ARGS_DEBUG) + "); publishing to server..."); } itemStatus.state = SyncState.LOCAL_DIRTY; mNetworkClient.putJson(pubPath, JsonSyncableItem.toJSON(mContext, localUri, c, syncMap)); } mLastUpdated.markUpdated(localUri); syncResult.stats.numEntries++; } // end for } finally { c.close(); } /* * Apply updates in bulk */ if (cpo.size() > 0) { if (DEBUG) { Log.d(TAG, "applying " + cpo.size() + " bulk updates..."); } final ContentProviderResult[] r = provider.applyBatch(cpo); if (DEBUG) { Log.d(TAG, "Done applying updates. Running postSync handler..."); } for (int i = 0; i < r.length; i++) { final ContentProviderResult res = r[i]; final SyncStatus ss = syncStatuses.get(cpoPubUris.get(i)); if (ss == null) { Log.e(TAG, "can't get sync status for " + res.uri); continue; } syncMap.onPostSyncItem(mContext, account, ss.local, ss.remoteJson, res.count != null ? res.count == 1 : true); ss.state = SyncState.NOW_UP_TO_DATE; } if (DEBUG) { Log.d(TAG, "done running postSync handler."); } cpo.clear(); cpoPubUris.clear(); } if (Thread.interrupted()) { throw new InterruptedException(); } /* * Look through the SyncState.state values and find ones that need to be stored. */ for (final Map.Entry<String, SyncStatus> entry : syncStatuses.entrySet()) { if (Thread.interrupted()) { throw new InterruptedException(); } final String pubUri = entry.getKey(); final SyncStatus status = entry.getValue(); if (status.state == SyncState.REMOTE_ONLY) { if (DEBUG) { Log.d(TAG, pubUri + " is not yet stored locally, adding..."); } // update this so it's in the local timescale correctServerOffset(status.remoteCVs, JsonSyncableItem._CREATED_DATE, JsonSyncableItem._CREATED_DATE, localOffset); correctServerOffset(status.remoteCVs, JsonSyncableItem._SERVER_MODIFIED_DATE, JsonSyncableItem._MODIFIED_DATE, localOffset); final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(toSync); b.withValues(status.remoteCVs); cpo.add(b.build()); cpoPubUris.add(pubUri); syncResult.stats.numInserts++; } } /* * Execute the content provider operations in bulk. */ if (cpo.size() > 0) { if (DEBUG) { Log.d(TAG, "bulk inserting " + cpo.size() + " items..."); } final ContentProviderResult[] r = provider.applyBatch(cpo); if (DEBUG) { Log.d(TAG, "applyBatch completed. Processing results..."); } int successful = 0; for (int i = 0; i < r.length; i++) { final ContentProviderResult res = r[i]; if (res.uri == null) { syncResult.stats.numSkippedEntries++; Log.e(TAG, "result from content provider bulk operation returned null"); continue; } final String pubUri = cpoPubUris.get(i); final SyncStatus ss = syncStatuses.get(pubUri); if (ss == null) { syncResult.stats.numSkippedEntries++; Log.e(TAG, "could not find sync status for " + cpoPubUris.get(i)); continue; } ss.local = res.uri; if (DEBUG) { Log.d(TAG, "onPostSyncItem(" + res.uri + ", ...); pubUri: " + pubUri); } syncMap.onPostSyncItem(mContext, account, res.uri, ss.remoteJson, res.count != null ? res.count == 1 : true); ss.state = SyncState.NOW_UP_TO_DATE; successful++; } if (DEBUG) { Log.d(TAG, successful + " batch inserts successfully applied."); } } else { if (DEBUG) { Log.d(TAG, "no updates to perform."); } } /** * Look through all the items that we didn't already find on the server side, but which * still have a public uri. They should be checked to make sure they're not deleted. */ c = provider.query(toSync, SYNC_PROJECTION, ProviderUtils.addExtraWhere(selectionInverse, JsonSyncableItem._PUBLIC_URI + " NOT NULL"), selectionArgs, null); try { final int idCol = c.getColumnIndex(JsonSyncableItem._ID); final int pubUriCol = c.getColumnIndex(JsonSyncableItem._PUBLIC_URI); cpo.clear(); for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { final String pubUri = c.getString(pubUriCol); SyncStatus ss = syncStatuses.get(pubUri); final Uri item = isDir ? ContentUris.withAppendedId(toSyncWithoutQuerystring, c.getLong(idCol)) : toSync; if (ss == null) { ss = syncStatuses.get(item.toString()); } if (DEBUG) { Log.d(TAG, item + " was not found in the main list of items on the server (" + pubPath + "), but appears to be a child of " + toSync); if (ss != null) { Log.d(TAG, "found sync status for " + item + ": " + ss); } } if (ss != null) { switch (ss.state) { case ALREADY_UP_TO_DATE: case NOW_UP_TO_DATE: if (DEBUG) { Log.d(TAG, item + " is already up to date. No need to see if it was deleted."); } continue; case BOTH_UNKNOWN: if (DEBUG) { Log.d(TAG, item + " was found on both sides, but has an unknown sync status. Skipping..."); } continue; default: Log.w(TAG, "got an unexpected state for " + item + ": " + ss); } } else { ss = new SyncStatus(pubUri, SyncState.LOCAL_ONLY); ss.local = item; hr = mNetworkClient.head(pubUri); switch (hr.getStatusLine().getStatusCode()) { case 200: if (DEBUG) { Log.d(TAG, "HEAD " + pubUri + " returned 200"); } ss.state = SyncState.BOTH_UNKNOWN; break; case 404: if (DEBUG) { Log.d(TAG, "HEAD " + pubUri + " returned 404. Deleting locally..."); } ss.state = SyncState.DELETED_REMOTELY; final ContentProviderOperation deleteOp = ContentProviderOperation .newDelete(ContentUris.withAppendedId(toSyncWithoutQuerystring, c.getLong(idCol))) .build(); cpo.add(deleteOp); break; default: syncResult.stats.numIoExceptions++; Log.w(TAG, "HEAD " + pubUri + " got unhandled result: " + hr.getStatusLine()); } } syncStatuses.put(pubUri, ss); } // for cursor if (cpo.size() > 0) { final ContentProviderResult[] results = provider.applyBatch(cpo); for (final ContentProviderResult result : results) { if (result.count != 1) { throw new SyncException("Error deleting item"); } } } } finally { c.close(); } syncStatuses.clear(); mLastUpdated.markUpdated(toSync); return true; }
From source file:de.vanita5.twittnuker.util.Utils.java
public static Uri appendQueryParameters(final Uri uri, final NameValuePair... params) { final Uri.Builder builder = uri.buildUpon(); if (params != null) { for (final NameValuePair param : params) { builder.appendQueryParameter(param.getName(), param.getValue()); }//from w w w . j av a 2 s . c o m } return builder.build(); }
From source file:edu.mit.mobile.android.locast.data.Sync.java
/** * Given a live cursor pointing to a data item and/or a set of contentValues loaded from the network, * attempt to sync.//from ww w. j a va 2 s. c o m * Either c or cvNet can be null, but not both. * @param c A cursor pointing to the data item. Null is OK here. * @param jsonObject JSON object for the item as loaded from the network. null is OK here. * @param sync An empty JsonSyncableItem object. * @param publicPath TODO * * @return True if the item has been modified on either end. * @throws IOException */ private boolean syncItem(Uri toSync, Cursor c, JSONObject jsonObject, JsonSyncableItem sync, SyncProgressNotifier syncProgress, String publicPath) throws SyncException, IOException { boolean modified = false; boolean needToCloseCursor = false; boolean toSyncIsIndex = false; final SyncMap syncMap = sync.getSyncMap(); Uri locUri = null; final Uri origToSync = toSync; ContentValues cvNet = null; final Context context = getApplicationContext(); final ContentResolver cr = context.getContentResolver(); if (jsonObject != null) { if ("http".equals(toSync.getScheme()) || "https".equals(toSync.getScheme())) { // we successfully loaded it from the 'net, but toSync is really for local URIs. Erase it. toSync = sync.getContentUri(); if (toSync == null) { if (DEBUG) { Log.w(TAG, "cannot get local URI for " + origToSync + ". Skipping..."); } return false; } } try { cvNet = JsonSyncableItem.fromJSON(context, null, jsonObject, syncMap); } catch (final Exception e) { final SyncException se = new SyncException("Problem loading JSON object."); se.initCause(e); throw se; } } final String contentType = cr.getType(toSync); if (c != null) { if (contentType.startsWith(CONTENT_TYPE_PREFIX_DIR)) { locUri = ContentUris.withAppendedId(toSync, c.getLong(c.getColumnIndex(JsonSyncableItem._ID))) .buildUpon().query(null).build(); toSyncIsIndex = true; } else { locUri = toSync; } // skip any items already sync'd if (mLastUpdated.isUpdatedRecently(locUri)) { return false; } final int draftCol = c.getColumnIndex(TaggableItem._DRAFT); if (draftCol != -1 && c.getInt(draftCol) != 0) { if (DEBUG) { Log.d(TAG, locUri + " is marked a draft. Not syncing."); } return false; } syncMap.onPreSyncItem(cr, locUri, c); } else if (contentType.startsWith(CONTENT_TYPE_PREFIX_DIR)) { // strip any query strings toSync = toSync.buildUpon().query(null).build(); } // if (c != null){ // MediaProvider.dumpCursorToLog(c, sync.getFullProjection()); // } // when the PUBLIC_URI is null, that means it's only local final int pubUriColumn = (c != null) ? c.getColumnIndex(JsonSyncableItem._PUBLIC_URI) : -1; if (c != null && (c.isNull(pubUriColumn) || c.getString(pubUriColumn) == "")) { // new content on the local side only. Gotta publish. try { jsonObject = JsonSyncableItem.toJSON(context, locUri, c, syncMap); if (publicPath == null) { publicPath = MediaProvider.getPostPath(this, locUri); } if (DEBUG) { Log.d(TAG, "Posting " + locUri + " to " + publicPath); } // The response from a post to create a new item should be the newly created item, // which contains the public ID that we need. jsonObject = nc.postJson(publicPath, jsonObject); final ContentValues cvUpdate = JsonSyncableItem.fromJSON(context, locUri, jsonObject, syncMap); if (cr.update(locUri, cvUpdate, null, null) == 1) { // at this point, server and client should be in sync. mLastUpdated.markUpdated(locUri); if (DEBUG) { Log.i(TAG, "Hooray! " + locUri + " has been posted succesfully."); } } else { Log.e(TAG, "update of " + locUri + " failed"); } modified = true; } catch (final Exception e) { final SyncException se = new SyncException(getString(R.string.error_sync_no_post)); se.initCause(e); throw se; } // only on the remote side, so pull it in. } else if (c == null && cvNet != null) { if (DEBUG) { Log.i(TAG, "Only on the remote side, using network-provided values."); } final String[] params = { cvNet.getAsString(JsonSyncableItem._PUBLIC_URI) }; c = cr.query(toSync, sync.getFullProjection(), JsonSyncableItem._PUBLIC_URI + "=?", params, null); needToCloseCursor = true; if (!c.moveToFirst()) { locUri = cr.insert(toSync, cvNet); modified = true; } else { locUri = ContentUris.withAppendedId(toSync, c.getLong(c.getColumnIndex(JsonSyncableItem._ID))) .buildUpon().query(null).build(); syncMap.onPreSyncItem(cr, locUri, c); } } // we've now found data on both sides, so sync them. if (!modified && c != null) { publicPath = c.getString(c.getColumnIndex(JsonSyncableItem._PUBLIC_URI)); try { if (cvNet == null) { try { if (publicPath == null && toSyncIsIndex && !MediaProvider.canSync(locUri)) { // At this point, we've already checked the index and it doesn't contain the item (otherwise it would be in the syncdItems). // If we can't sync individual items, it's possible that the index is paged or the item has been deleted. if (DEBUG) { Log.w(TAG, "Asked to sync " + locUri + " but item wasn't in server index and cannot sync individual entries. Skipping and hoping it is up to date."); } return false; } else { if (mLastUpdated.isUpdatedRecently(nc.getFullUri(publicPath))) { if (DEBUG) { Log.d(TAG, "already sync'd! " + publicPath); } return false; } if (jsonObject == null) { jsonObject = nc.getObject(publicPath); } cvNet = JsonSyncableItem.fromJSON(context, locUri, jsonObject, syncMap); } } catch (final HttpResponseException hre) { if (hre.getStatusCode() == HttpStatus.SC_NOT_FOUND) { final SyncItemDeletedException side = new SyncItemDeletedException(locUri); side.initCause(hre); throw side; } } } if (cvNet == null) { Log.e(TAG, "got null values from fromJSON() on item " + locUri + ": " + (jsonObject != null ? jsonObject.toString() : "<< no json object >>")); return false; } final Date netLastModified = new Date(cvNet.getAsLong(JsonSyncableItem._MODIFIED_DATE)); final Date locLastModified = new Date(c.getLong(c.getColumnIndex(JsonSyncableItem._MODIFIED_DATE))); if (netLastModified.equals(locLastModified)) { // same! yay! We don't need to do anything. if (DEBUG) { Log.d("LocastSync", locUri + " doesn't need to sync."); } } else if (netLastModified.after(locLastModified)) { // remote is more up to date, update! cr.update(locUri, cvNet, null, null); if (DEBUG) { Log.d("LocastSync", cvNet + " is newer than " + locUri); } modified = true; } else if (netLastModified.before(locLastModified)) { // local is more up to date, propagate! jsonObject = nc.putJson(publicPath, JsonSyncableItem.toJSON(context, locUri, c, syncMap)); if (DEBUG) { Log.d("LocastSync", cvNet + " is older than " + locUri); } modified = true; } mLastUpdated.markUpdated(nc.getFullUri(publicPath)); } catch (final JSONException e) { final SyncException se = new SyncException( "Item sync error for path " + publicPath + ": invalid JSON."); se.initCause(e); throw se; } catch (final NetworkProtocolException e) { final SyncException se = new SyncException( "Item sync error for path " + publicPath + ": " + e.getHttpResponseMessage()); se.initCause(e); throw se; } finally { if (needToCloseCursor) { c.close(); needToCloseCursor = false; } } } if (needToCloseCursor) { c.close(); } if (locUri == null) { throw new RuntimeException("Never got a local URI for a sync'd item."); } // two calls are made in two different contexts. Which context you use depends on the application. syncMap.onPostSyncItem(context, locUri, jsonObject, modified); sync.onPostSyncItem(context, locUri, jsonObject, modified); mLastUpdated.markUpdated(locUri); // needed for things that may have requested a sync with a different URI than what was eventually produced. if (origToSync != locUri) { mLastUpdated.markUpdated(origToSync); cr.notifyChange(origToSync, null); } return modified; }
From source file:group.pals.android.lib.ui.filechooser.FragmentFiles.java
/** * Deletes a file.//from ww w .ja v a2s.c o m * * @param position * the position of item to be delete. */ private void deleteFile(final int position) { Cursor cursor = (Cursor) mFileAdapter.getItem(position); /* * The cursor can be changed if the list view is updated, so we take its * properties here. */ final boolean isFile = BaseFileProviderUtils.isFile(cursor); final String filename = BaseFileProviderUtils.getFileName(cursor); if (!BaseFileProviderUtils.fileCanWrite(cursor)) { Dlg.toast(getActivity(), getString(R.string.afc_pmsg_cannot_delete_file, isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder), filename), Dlg.LENGTH_SHORT); return; } if (LocalFileContract.getAuthority(getActivity()).equals(mFileProviderAuthority) && !Utils.hasPermissions(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Dlg.toast(getActivity(), R.string.afc_msg_app_doesnot_have_permission_to_delete_files, Dlg.LENGTH_SHORT); return; } /* * The cursor can be changed if the list view is updated, so we take its * properties here. */ final int id = cursor.getInt(cursor.getColumnIndex(BaseFile._ID)); final Uri uri = BaseFileProviderUtils.getUri(cursor); mFileAdapter.markItemAsDeleted(id, true); Dlg.confirmYesno(getActivity(), getString(R.string.afc_pmsg_confirm_delete_file, isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder), filename), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new LoadingDialog<Void, Void, Boolean>(getActivity(), getString(R.string.afc_pmsg_deleting_file, isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder), filename), true) { final int taskId = EnvUtils.genId(); private void notifyFileDeleted() { Dlg.toast(getActivity(), getString(R.string.afc_pmsg_file_has_been_deleted, isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder), filename), Dlg.LENGTH_SHORT); }// notifyFileDeleted() @Override protected Boolean doInBackground(Void... params) { getActivity().getContentResolver().delete(uri.buildUpon() .appendQueryParameter(BaseFile.PARAM_TASK_ID, Integer.toString(taskId)) .build(), null, null); return !BaseFileProviderUtils.fileExists(getActivity(), uri); }// doInBackground() @Override protected void onCancelled() { if (getCurrentLocation() != null) BaseFileProviderUtils.cancelTask(getActivity(), getCurrentLocation().getAuthority(), taskId); new LoadingDialog<Void, Void, Boolean>(getActivity(), false) { @Override protected Boolean doInBackground(Void... params) { return BaseFileProviderUtils.fileExists(getActivity(), uri); }// doInBackground() @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { mFileAdapter.markItemAsDeleted(id, false); Dlg.toast(getActivity(), R.string.afc_msg_cancelled, Dlg.LENGTH_SHORT); } else notifyFileDeleted(); }// onPostExecute() }.execute(); super.onCancelled(); }// onCancelled() @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { notifyFileDeleted(); } else { mFileAdapter.markItemAsDeleted(id, false); Dlg.toast(getActivity(), getString(R.string.afc_pmsg_cannot_delete_file, isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder), filename), Dlg.LENGTH_SHORT); } }// onPostExecute() }.execute();// LoadingDialog }// onClick() }, new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { mFileAdapter.markItemAsDeleted(id, false); }// onCancel() }); }
From source file:com.haibison.android.anhuu.FragmentFiles.java
/** * Deletes a file./* w ww. j ava 2s . co m*/ * * @param position * the position of item to be delete. */ private void deleteFile(final int position) { Cursor cursor = (Cursor) mFileAdapter.getItem(position); /* * The cursor can be changed if the list view is updated, so we take its * properties here. */ final boolean isFile = BaseFileProviderUtils.isFile(cursor); final String filename = BaseFileProviderUtils.getFileName(cursor); if (!BaseFileProviderUtils.fileCanWrite(cursor)) { Dlg.toast(getActivity(), getString(R.string.anhuu_f5be488d_pmsg_cannot_delete_file, isFile ? getString(R.string.anhuu_f5be488d_file) : getString(R.string.anhuu_f5be488d_folder), filename), Dlg.LENGTH_SHORT); return; } if (LocalFileContract.getAuthority(getActivity()).equals(mFileProviderAuthority) && !Utils.hasPermissions(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Dlg.toast(getActivity(), R.string.anhuu_f5be488d_msg_app_doesnot_have_permission_to_delete_files, Dlg.LENGTH_SHORT); return; } /* * The cursor can be changed if the list view is updated, so we take its * properties here. */ final int id = cursor.getInt(cursor.getColumnIndex(BaseFile._ID)); final Uri uri = BaseFileProviderUtils.getUri(cursor); mFileAdapter.markItemAsDeleted(id, true); Dlg.confirmYesno(getActivity(), getString(R.string.anhuu_f5be488d_pmsg_confirm_delete_file, isFile ? getString(R.string.anhuu_f5be488d_file) : getString(R.string.anhuu_f5be488d_folder), filename), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new LoadingDialog<Void, Void, Boolean>(getActivity(), getString(R.string.anhuu_f5be488d_pmsg_deleting_file, isFile ? getString(R.string.anhuu_f5be488d_file) : getString(R.string.anhuu_f5be488d_folder), filename), true) { final int taskId = EnvUtils.genId(); private void notifyFileDeleted() { Dlg.toast(getActivity(), getString(R.string.anhuu_f5be488d_pmsg_file_has_been_deleted, isFile ? getString(R.string.anhuu_f5be488d_file) : getString(R.string.anhuu_f5be488d_folder), filename), Dlg.LENGTH_SHORT); }// notifyFileDeleted() @Override protected Boolean doInBackground(Void... params) { getActivity().getContentResolver().delete(uri.buildUpon() .appendQueryParameter(BaseFile.PARAM_TASK_ID, Integer.toString(taskId)) .build(), null, null); return !BaseFileProviderUtils.fileExists(getActivity(), uri); }// doInBackground() @Override protected void onCancelled() { if (getCurrentLocation() != null) BaseFileProviderUtils.cancelTask(getActivity(), getCurrentLocation().getAuthority(), taskId); new LoadingDialog<Void, Void, Boolean>(getActivity(), false) { @Override protected Boolean doInBackground(Void... params) { return BaseFileProviderUtils.fileExists(getActivity(), uri); }// doInBackground() @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { mFileAdapter.markItemAsDeleted(id, false); Dlg.toast(getActivity(), R.string.anhuu_f5be488d_msg_cancelled, Dlg.LENGTH_SHORT); } else notifyFileDeleted(); }// onPostExecute() }.execute(); super.onCancelled(); }// onCancelled() @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { notifyFileDeleted(); } else { mFileAdapter.markItemAsDeleted(id, false); Dlg.toast(getActivity(), getString(R.string.anhuu_f5be488d_pmsg_cannot_delete_file, isFile ? getString(R.string.anhuu_f5be488d_file) : getString(R.string.anhuu_f5be488d_folder), filename), Dlg.LENGTH_SHORT); } }// onPostExecute() }.execute();// LoadingDialog }// onClick() }, new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { mFileAdapter.markItemAsDeleted(id, false); }// onCancel() }); }
From source file:org.voidsink.anewjkuapp.update.ImportCalendarTask.java
@Override public Void call() throws Exception { if (mProvider == null) { return null; }//from w w w . java2 s .co m if ((ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) || (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED)) { return null; } if (!CalendarUtils.getSyncCalendar(mContext, this.mCalendarName)) { return null; } if (mShowProgress) { mUpdateNotification = new SyncNotification(mContext, R.string.notification_sync_calendar); mUpdateNotification.show(mContext.getString(R.string.notification_sync_calendar_loading, CalendarUtils.getCalendarName(mContext, this.mCalendarName))); } CalendarChangedNotification mNotification = new CalendarChangedNotification(mContext, CalendarUtils.getCalendarName(mContext, this.mCalendarName)); try { Log.d(TAG, "setup connection"); updateNotify(mContext.getString(R.string.notification_sync_connect)); if (KusssHandler.getInstance().isAvailable(mContext, AppUtils.getAccountAuthToken(mContext, mAccount), AppUtils.getAccountName(mContext, mAccount), AppUtils.getAccountPassword(mContext, mAccount))) { updateNotify(mContext.getString(R.string.notification_sync_calendar_loading, CalendarUtils.getCalendarName(mContext, this.mCalendarName))); Log.d(TAG, "loading calendar"); Calendar iCal; String kusssIdPrefix; // {{ Load calendar events from resource switch (this.mCalendarName) { case CalendarUtils.ARG_CALENDAR_EXAM: iCal = KusssHandler.getInstance().getExamIcal(mContext, mCalendarBuilder); kusssIdPrefix = "at-jku-kusss-exam-"; break; case CalendarUtils.ARG_CALENDAR_COURSE: iCal = KusssHandler.getInstance().getLVAIcal(mContext, mCalendarBuilder); kusssIdPrefix = "at-jku-kusss-coursedate-"; break; default: { Log.w(TAG, "calendar not found: " + this.mCalendarName); return null; } } if (iCal == null) { Log.w(TAG, "calendar not loaded: " + this.mCalendarName); mSyncResult.stats.numParseExceptions++; return null; } List<?> events = iCal.getComponents(Component.VEVENT); Log.d(TAG, String.format("got %d events", events.size())); updateNotify(mContext.getString(R.string.notification_sync_calendar_updating, CalendarUtils.getCalendarName(mContext, this.mCalendarName))); ArrayList<ContentProviderOperation> batch = new ArrayList<>(); // modify events: move courseId/term and lecturer to description String lineSeparator = System.getProperty("line.separator"); if (lineSeparator == null) lineSeparator = ", "; Map<String, VEvent> eventsMap = new HashMap<>(); for (Object e : events) { if (VEvent.class.isInstance(e)) { VEvent ev = ((VEvent) e); String summary = ev.getSummary().getValue().trim(); String description = ev.getDescription().getValue().trim(); Matcher courseIdTermMatcher = courseIdTermPattern.matcher(summary); // (courseId/term) if (courseIdTermMatcher.find()) { if (!description.isEmpty()) { description += lineSeparator; description += lineSeparator; } description += summary.substring(courseIdTermMatcher.start()); summary = summary.substring(0, courseIdTermMatcher.start()); } else { Matcher lecturerMatcher = lecturerPattern.matcher(summary); if (lecturerMatcher.find()) { if (!description.isEmpty()) { description += lineSeparator; description += lineSeparator; } description += summary.substring(lecturerMatcher.start()); summary = summary.substring(0, lecturerMatcher.start()); } } summary = summary.trim().replaceAll("([\\r\\n]|\\\\n)+", ", ").trim(); description = description.trim(); ev.getProperty(Property.SUMMARY).setValue(summary); ev.getProperty(Property.DESCRIPTION).setValue(description); } } // Build hash table of incoming entries for (Object e : events) { if (VEvent.class.isInstance(e)) { VEvent ev = ((VEvent) e); String uid = ev.getUid().getValue(); // compense DST eventsMap.put(uid, ev); } } String calendarId = CalendarUtils.getCalIDByName(mContext, mAccount, mCalendarName, true); if (calendarId == null) { Log.w(TAG, "calendarId not found"); return null; } String mCalendarAccountName = mAccount.name; String mCalendarAccountType = mAccount.type; try { Cursor c = mProvider.query(CalendarContractWrapper.Calendars.CONTENT_URI(), CalendarUtils.CALENDAR_PROJECTION, null, null, null); if (c != null) { while (c.moveToNext()) { if (calendarId.equals(c.getString(CalendarUtils.COLUMN_CAL_ID))) { mCalendarAccountName = c.getString(CalendarUtils.COLUMN_CAL_ACCOUNT_NAME); mCalendarAccountType = c.getString(CalendarUtils.COLUMN_CAL_ACCOUNT_TYPE); break; } } c.close(); } } catch (Exception e) { return null; } Log.d(TAG, "Fetching local entries for merge with: " + calendarId); Uri calUri = CalendarContractWrapper.Events.CONTENT_URI(); Cursor c = CalendarUtils.loadEvent(mProvider, calUri, calendarId); if (c == null) { Log.w(TAG, "selection failed"); } else { Log.d(TAG, String.format("Found %d local entries. Computing merge solution...", c.getCount())); // find stale data String eventId; String eventKusssId; String eventLocation; String eventTitle; String eventDescription; long eventDTStart; long eventDTEnd; boolean eventDirty; boolean eventDeleted; // calc date for notifiying only future changes // max update interval is 1 week long notifyFrom = new Date().getTime() - (DateUtils.DAY_IN_MILLIS * 7); while (c.moveToNext()) { mSyncResult.stats.numEntries++; eventId = c.getString(CalendarUtils.COLUMN_EVENT_ID); // Log.d(TAG, "---------"); eventKusssId = null; // get kusssId from extended properties Cursor c2 = mProvider.query(CalendarContract.ExtendedProperties.CONTENT_URI, CalendarUtils.EXTENDED_PROPERTIES_PROJECTION, CalendarContract.ExtendedProperties.EVENT_ID + " = ?", new String[] { eventId }, null); if (c2 != null) { while (c2.moveToNext()) { // String extra = ""; // for (int i = 0; i < c2.getColumnCount(); i++) { // extra = extra + i + "=" + c2.getString(i) + ";"; // } // Log.d(TAG, "Extended: " + extra); if (c2.getString(1).contains(CalendarUtils.EXTENDED_PROPERTY_NAME_KUSSS_ID)) { eventKusssId = c2.getString(2); } } c2.close(); } if (TextUtils.isEmpty(eventKusssId)) { eventKusssId = c.getString(CalendarUtils.COLUMN_EVENT_KUSSS_ID_LEGACY); } eventTitle = c.getString(CalendarUtils.COLUMN_EVENT_TITLE); Log.d(TAG, "Title: " + eventTitle); eventLocation = c.getString(CalendarUtils.COLUMN_EVENT_LOCATION); eventDescription = c.getString(CalendarUtils.COLUMN_EVENT_DESCRIPTION); eventDTStart = c.getLong(CalendarUtils.COLUMN_EVENT_DTSTART); eventDTEnd = c.getLong(CalendarUtils.COLUMN_EVENT_DTEND); eventDirty = "1".equals(c.getString(CalendarUtils.COLUMN_EVENT_DIRTY)); eventDeleted = "1".equals(c.getString(CalendarUtils.COLUMN_EVENT_DELETED)); if (eventKusssId != null && kusssIdPrefix != null && eventKusssId.startsWith(kusssIdPrefix)) { VEvent match = eventsMap.get(eventKusssId); if (match != null && !eventDeleted) { // Entry exists. Remove from entry // map to prevent insert later eventsMap.remove(eventKusssId); // update only changes after notifiyFrom if ((match.getStartDate().getDate().getTime() > notifyFrom || eventDTStart > notifyFrom) && // check to see if the entry needs to be updated ((match.getStartDate().getDate().getTime() != eventDTStart) || (match.getEndDate().getDate().getTime() != eventDTEnd) || (!match.getSummary().getValue().trim().equals(eventTitle.trim())) || (!match.getSummary().getValue().trim().equals(eventTitle.trim())) || (!match.getLocation().getValue().trim() .equals(eventLocation.trim())) || (!match.getDescription().getValue().trim() .equals(eventDescription.trim())))) { Uri existingUri = calUri.buildUpon().appendPath(eventId).build(); // Update existing record Log.d(TAG, "Scheduling update: " + existingUri + " dirty=" + eventDirty); batch.add(ContentProviderOperation.newUpdate(existingUri) .withValues(getContentValuesFromEvent(match)).build()); mSyncResult.stats.numUpdates++; mNotification.addUpdate(getEventString(mContext, match)); } else { mSyncResult.stats.numSkippedEntries++; } } else { if (eventDTStart > (mSyncFromNow - DateUtils.DAY_IN_MILLIS)) { // Entry doesn't exist. Remove only newer events from the database. Uri deleteUri = calUri.buildUpon().appendPath(eventId).build(); Log.d(TAG, "Scheduling delete: " + deleteUri); // notify only future changes if (eventDTStart > notifyFrom && !eventDeleted) { mNotification.addDelete(AppUtils.getEventString(mContext, eventDTStart, eventDTEnd, eventTitle, false)); } batch.add(ContentProviderOperation.newDelete(deleteUri).build()); mSyncResult.stats.numDeletes++; } else { mSyncResult.stats.numSkippedEntries++; } } } else { Log.i(TAG, "Event UID not set, ignore event: uid=" + eventKusssId + " dirty=" + eventDirty + " title=" + eventTitle); } } c.close(); Log.d(TAG, String.format("Cursor closed, %d events left", eventsMap.size())); updateNotify(mContext.getString(R.string.notification_sync_calendar_adding, CalendarUtils.getCalendarName(mContext, this.mCalendarName))); // Add new items for (VEvent v : eventsMap.values()) { if (v.getUid().getValue().startsWith(kusssIdPrefix)) { // notify only future changes if (v.getStartDate().getDate().getTime() > notifyFrom) { mNotification.addInsert(getEventString(mContext, v)); } Builder builder = ContentProviderOperation .newInsert(CalendarContractWrapper.Events.CONTENT_URI()); builder.withValue(CalendarContractWrapper.Events.CALENDAR_ID(), calendarId) .withValues(getContentValuesFromEvent(v)) .withValue(CalendarContractWrapper.Events.EVENT_TIMEZONE(), TimeZone.getDefault().getID()); if (mCalendarName.equals(CalendarUtils.ARG_CALENDAR_EXAM)) { builder.withValue(CalendarContractWrapper.Events.AVAILABILITY(), CalendarContractWrapper.Events.AVAILABILITY_BUSY()); } else { builder.withValue(CalendarContractWrapper.Events.AVAILABILITY(), CalendarContractWrapper.Events.AVAILABILITY_FREE()); } builder.withValue(CalendarContract.Events.STATUS, CalendarContract.Events.STATUS_TENTATIVE); builder.withValue(CalendarContract.Events.HAS_ALARM, "0"); builder.withValue(CalendarContract.Events.HAS_ATTENDEE_DATA, "0"); builder.withValue(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, "1"); ContentProviderOperation op = builder.build(); Log.d(TAG, "Scheduling insert: " + v.getUid().getValue()); batch.add(op); int eventIndex = batch.size() - 1; // add kusssid as extendet property batch.add(ContentProviderOperation .newInsert(KusssContentContract.asEventSyncAdapter( CalendarContract.ExtendedProperties.CONTENT_URI, mAccount.name, mAccount.type)) .withValueBackReference(CalendarContract.ExtendedProperties.EVENT_ID, eventIndex) .withValue(CalendarContract.ExtendedProperties.NAME, CalendarUtils.EXTENDED_PROPERTY_NAME_KUSSS_ID) .withValue(CalendarContract.ExtendedProperties.VALUE, v.getUid().getValue()) .build()); // add location extra for google maps batch.add(ContentProviderOperation .newInsert(KusssContentContract.asEventSyncAdapter( CalendarContract.ExtendedProperties.CONTENT_URI, mAccount.name, mAccount.type)) .withValueBackReference(CalendarContract.ExtendedProperties.EVENT_ID, eventIndex) .withValue(CalendarContract.ExtendedProperties.NAME, CalendarUtils.EXTENDED_PROPERTY_LOCATION_EXTRA) .withValue(CalendarContract.ExtendedProperties.VALUE, getLocationExtra(v)) .build()); mSyncResult.stats.numInserts++; } else { mSyncResult.stats.numSkippedEntries++; } } if (batch.size() > 0) { updateNotify(mContext.getString(R.string.notification_sync_calendar_saving, CalendarUtils.getCalendarName(mContext, this.mCalendarName))); Log.d(TAG, "Applying batch update"); mProvider.applyBatch(batch); Log.d(TAG, "Notify resolver"); mResolver.notifyChange(calUri.buildUpon().appendPath(calendarId).build(), // URI // where // data // was // modified null, // No local observer false); // IMPORTANT: Do not sync to // network } else { Log.w(TAG, "No batch operations found! Do nothing"); } } KusssHandler.getInstance().logout(mContext); } else { mSyncResult.stats.numAuthExceptions++; } } catch (Exception e) { Analytics.sendException(mContext, e, true); Log.e(TAG, "import calendar failed", e); } if (mUpdateNotification != null) { mUpdateNotification.cancel(); } mNotification.show(); if (mReleaseProvider) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mProvider.close(); } else { mProvider.release(); } } return null; }