I am not getting to update my entry, before I try to update, I unpublish the entry using client.entries().async().unPublish(entry), and it works, but when I try to update using the code below, I receive the follow message: java.lang.IllegalArgumentException: entry must have a space associated.
What am I doing wrong?
final CMAClient client =
new CMAClient
.Builder()
.setAccessToken(contentfulConnection.getCMA_TOKEN())
.build();
final CMASystem sys = new CMASystem();
sys.setId(entryID).setVersion(CurrentVersion);
CMAEntry entry;
entry.setField("name", "en-US", "TEST").setSystem(sys);
entry.setSpaceId(SPACE_ID);
entry.setID("entryID");
client.entries().async().update(entry, new CMACallback<CMAEntry>() {
#Override protected void onSuccess(CMAEntry entry) {
// Successfully created a new entry.
new AlertDialog.Builder(ctx).setTitle("Contentful")
.setMessage("Creation of an entry was successful." +"\n\nResult:
" +
entry).show();
} }
#Override protected void onFailure(RuntimeException exception) {
// An error occurred! Inform the user.
new AlertDialog.Builder(ctx)
.setTitle("Contentful Error")
.setMessage("Could not create an entry." +
"\n\nReason: " + exception.toString())
.show();
System.out.println(exception.toString());
super.onFailure(exception);
}
}
);
I am a maintainer of the Contentful Java SDK.
The recommended way of using the update method is to first fetch an item, change its data and then update it again.
If you follow this link to our documentation, and select the create/update an entry button, you'll see a code snippets on how to update entries. Please select Android platform to see it for Android.
I hope this helps you a bit further.
Related
I am using Realm MongoDB for my android app, and I have a problem:
I have different users in my app, and each user has his "cards". The partition of each user's cards is:
"Card=userID".
So, I want to be able to send a card from one user to the other. I do it via a link that includes userID and specific cardID.
So my code looks something like:
Realm.init(this);
mainApp = new App(new AppConfiguration.Builder(APP_ID).defaultSyncErrorHandler((session, error) ->
Log.e("TAG()", "Sync error: ${error.errorMessage}")
).build());
//TEMP CODE
String partition = "Card=611d7n582w36796ce34af106"; //test partition of another user
if(mainApp.currentUser() != null) {
SyncConfiguration config = new SyncConfiguration.Builder(
mainApp.currentUser(),
partition)
.build();
Realm realmLinkCard = Realm.getInstance(config);
Log.d(TAG, "onCreate: cards found- " + realmLinkCard.where(Card.class).findAll().size());
}
The last log always shows 0. I know there are cards for sure because if the user that created the corresponding partition is signed in then it does find the cards.
permissions are set to true for both read and write for the whole sync.
What can the problem be?
You cannot access a Realm by a user who has a different partition.
Instead you can create a mongodb function and call it from your user.
Make your function here:
Check here on How to create a function
And call it by checking here on How to call a function from client
Quick example of a realm function:
exports = async function funcName(partition) {
const cluster = context.services.get('myclustername');
const mycollection = cluster.db('mydbname').collection('mycollectionname');
let result = [];
try {
result = mycollection.findOne({
_partition: partition,
});
} catch (e) {
result.push(e);
return result;
}
return result;
};
To call it, please see above for the documentation as I'm not an Android developper.
My goal is to create an Android app which download a map from ArcGIS portal when connected to internet, then use them offline. I would like to use service pattern, so later the app can have synchronization feature. I followed a tutorial from ArcGIS here.
I am currently stuck at downloading the map part. I expect the downloaded map is in mobile map package (.mmpk), but instead my download directory have a package.info file, and a folder of geodatabase and .mmap files as image shown here. Based on my understanding, I should have an .mmpk file to use them offline.
Following the tutorial steps, I am able to (1) create an offline map task, (2) specify the parameters, and (3) examine the offline capabilities. However in step (4) generate and download the offline map, I expect the downloaded map will be in mobile map package (.mmpk) but its not; as i mentioned above with image shown. In step (5) open and use the offline map, i am able to view offline map when using mobile map package (.mmpk) file that i transfer manually into the device. I also tried to open and use my downloaded (.mmap) file but no map showed up.
My full code by steps is shown below:
(1) create an offline map task
// Load map from a portal item
final Portal portal = new Portal("http://www.arcgis.com");
final PortalItem webmapItem = new PortalItem(portal, "acc027394bc84c2fb04d1ed317aac674");
// Create map and add it to the view
myMap = new ArcGISMap(webmapItem);
mMapView = (MapView) findViewById(R.id.mapView);
mMapView.setMap(myMap);
// Create task and set parameters
final OfflineMapTask offlineMapTask = new OfflineMapTask(myMap);
(2) specify the parameters
// Create default parameters
final ListenableFuture<GenerateOfflineMapParameters> parametersFuture = offlineMapTask.createDefaultGenerateOfflineMapParametersAsync(areaOfInterest);
parametersFuture.addDoneListener(new Runnable() {
#Override
public void run() {
try {
final GenerateOfflineMapParameters parameters = parametersFuture.get();
// Update the parameters if needed
// Limit maximum scale to 5000 but take all the scales above (use 0 as a MinScale)
parameters.setMaxScale(5000);
parameters.setIncludeBasemap(false);
// Set attachment options
parameters.setAttachmentSyncDirection(GenerateGeodatabaseParameters.AttachmentSyncDirection.UPLOAD);
parameters.setReturnLayerAttachmentOption(GenerateOfflineMapParameters.ReturnLayerAttachmentOption.EDITABLE_LAYERS);
// Request the table schema only (existing features won't be included)
parameters.setReturnSchemaOnlyForEditableLayers(true);
// Update the title to contain the region
parameters.getItemInfo().setTitle(parameters.getItemInfo().getTitle() + " (Central)");
// Create new item info
final OfflineMapItemInfo itemInfo = new OfflineMapItemInfo();
// Override thumbnail with the new image based on the extent
final ListenableFuture<Bitmap> exportImageFuture = mMapView.exportImageAsync();
exportImageFuture.addDoneListener(new Runnable() {
#Override
public void run() {
try {
Bitmap mapImage = exportImageFuture.get();
// Scale to thumbnail size
Bitmap thumbnailImage = Bitmap.createScaledBitmap(mapImage, 200, 133, false);
// Convert to byte[]
ByteArrayOutputStream stream = new ByteArrayOutputStream();
thumbnailImage.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] thumbnailBytes = stream.toByteArray();
stream.close();
// Set values to the itemInfo
itemInfo.setThumbnailData(thumbnailBytes);
itemInfo.setTitle("Water network (Central)");
itemInfo.setSnippet(webmapItem.getSnippet()); // Copy from the source map
itemInfo.setDescription(webmapItem.getDescription()); // Copy from the source map
itemInfo.setAccessInformation(webmapItem.getAccessInformation()); // Copy from the source map
itemInfo.getTags().add("Water network");
itemInfo.getTags().add("Data validation");
// Set metadata to parameters
parameters.setItemInfo(itemInfo);
} catch (Exception e) {
e.printStackTrace();
}
}
});
(3) examine the offline capabilities
final ListenableFuture<OfflineMapCapabilities> offlineMapCapabilitiesFuture =
offlineMapTask.getOfflineMapCapabilitiesAsync(parameters);
offlineMapCapabilitiesFuture.addDoneListener(new Runnable() {
#Override
public void run() {
try {
OfflineMapCapabilities offlineMapCapabilities = offlineMapCapabilitiesFuture.get();
if (offlineMapCapabilities.hasErrors()) {
// Handle possible errors with layers
for (java.util.Map.Entry<Layer, OfflineCapability> layerCapability :
offlineMapCapabilities.getLayerCapabilities().entrySet()) {
if (!layerCapability.getValue().isSupportsOffline()) {
showMessage(layerCapability.getKey().getName() + " cannot be taken offline.");
showMessage("Error : " + layerCapability.getValue().getError().getMessage());
}
}
// Handle possible errors with tables
for (java.util.Map.Entry<FeatureTable, OfflineCapability> tableCapability :
offlineMapCapabilities.getTableCapabilities().entrySet()) {
if (!tableCapability.getValue().isSupportsOffline()) {
showMessage(tableCapability.getKey().getTableName() + " cannot be taken offline.");
showMessage("Error : " + tableCapability.getValue().getError().getMessage());
}
}
} else {
// All layers and tables can be taken offline!
showMessage("All layers are good to go!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
(4) generate and download the offline map
String mExportPath = String.valueOf(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)) + File.separator + "New";
showMessage(mExportPath);
// Create and start a job to generate the offline map
final GenerateOfflineMapJob generateOfflineJob =
offlineMapTask.generateOfflineMap(parameters, mExportPath);
// Show that job started
final ProgressBar progressBarOffline = (ProgressBar) findViewById(R.id.progressBarOffline);
progressBarOffline.setVisibility(View.VISIBLE);
generateOfflineJob.start();
generateOfflineJob.addJobDoneListener(new Runnable() {
#Override
public void run() {
// Generate the offline map and download it
GenerateOfflineMapResult result = generateOfflineJob.getResult();
if (!result.hasErrors()) {
showMessage("no error");
mobileMapPackage = result.getMobileMapPackage();
// Job is finished and all content was generated
showMessage("Map " + mobileMapPackage.getItem().getTitle() +
" saved to " + mobileMapPackage.getPath());
// Show offline map in a MapView
mMapView.setMap(result.getOfflineMap());
// Show that job completed
progressBarOffline.setVisibility(View.INVISIBLE);
} else {
showMessage("error");
// Job is finished but some of the layers/tables had errors
if (result.getLayerErrors().size() > 0) {
for (java.util.Map.Entry<Layer, ArcGISRuntimeException> layerError : result.getLayerErrors().entrySet()) {
showMessage("Error occurred when taking " + layerError.getKey().getName() + " offline.");
showMessage("Error : " + layerError.getValue().getMessage());
}
}
if (result.getTableErrors().size() > 0) {
for (java.util.Map.Entry<FeatureTable, ArcGISRuntimeException> tableError : result.getTableErrors().entrySet()) {
showMessage("Error occurred when taking " + tableError.getKey().getTableName() + " offline.");
showMessage("Error : " + tableError.getValue().getMessage());
}
}
// Show that job completed
progressBarOffline.setVisibility(View.INVISIBLE);
}
}
});
(5) open and use the offline map
// Create the mobile map package
final MobileMapPackage mapPackage = new MobileMapPackage(mobileMapPackage.getPath());
// Load the mobile map package asynchronously
mapPackage.loadAsync();
// Add done listener which will invoke when mobile map package has loaded
mapPackage.addDoneLoadingListener(new Runnable() {
#Override
public void run() {
// Check load status and that the mobile map package has maps
if(mapPackage.getLoadStatus() == LoadStatus.LOADED && mapPackage.getMaps().size() > 0){
// Cdd the map from the mobile map package to the MapView
mMapView.setMap(mapPackage.getMaps().get(0));
}else{
// Log an issue if the mobile map package fails to load
showMessage(mapPackage.getLoadError().getMessage());
}
}
});
showMessage() in my code is showing Toast.
public void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
I worry if my .mmpk expectation is wrong, or my step goes wrong somewhere because I still not fully understand the whole process. This is my first time working with ArcGIS map in Android. I could not find much sample code to experiment, so really appreciate someone who could help.
Thank you!
The task created an exploded mobile map package, which works just the same as a .mmpk file. Open it like this:
final MobileMapPackage mapPackage =
new MobileMapPackage("/data/com.geoinfo.asmasyakirah.arcgis/files/Documents/New");
(If you can't access it there, you might want to generate the mobile map package in Environment.getExternalStorageDirectory() instead of Environment.DIRECTORY_DOCUMENTS.)
According to the documentation for the MobileMapPackage constructor:
Creates a new MobileMapPackage from the .mmpk file or exploded mobile map package at the given path.
If you really must have it as a .mmpk file, simply zip it using an Android API for making zip files and name it .mmpk instead of .zip.
Kinda late on the topic but i had several days working on this and found out something that may help some of you :
I created my mapData via this class : https://github.com/Esri/arcgis-runtime-samples-java/blob/master/src/main/java/com/esri/samples/map/generate_offline_map/GenerateOfflineMapSample.java
As you can see it creates a folder containing package.info + p13 (in which you find geodatabase file + mmap file)
WHen i tried offline to load this data, no errors appeared but the layer was empty and i could just see the carroying.
In fact after much more tries, i had to check that besides geodatabase and mmap file i could find a .tpk file (TilePackaged)
This one was never available (somehow due to network issues during the online download) and nothing alerted me.
Now that this tpk file is there, all items are clearly displayed like 'water network'
TL;DR; : check that tpk file is donwloaded during the online preparation.
I'm almost finished with my application where I'm able to do a simple delete off of Google Spraedsheet data. However, I have not been able to find a method where I could add the sheetId and its respective GID # to the request arraylist.
private void deleteRow()
{
List<Request> requests = new ArrayList<>();
DeleteDimensionRequest deleteDimensionRequest = new DeleteDimensionRequest();
DimensionRange dimensionRange = new DimensionRange();
dimensionRange.getDimension();
dimensionRange.setStartIndex(13);
dimensionRange.setEndIndex(14);
deleteDimensionRequest.setRange(dimensionRange);
Sheets.Spreadsheets spreadsheets = null;
requests.add(new Request()
//There should be a function call or some sort for me to
//add a sheetid... if I do the updatesheets property here
//I get an error message saying that there's already a kind
//and I cannot set the id
.setDeleteDimension(deleteDimensionRequest)
);
BatchUpdateSpreadsheetRequest batchUpdateRequest = new BatchUpdateSpreadsheetRequest()
.setRequests(requests);
try
{
mService.spreadsheets().batchUpdate("SPREADSHEETID GOES HERE", batchUpdateRequest).execute();
}
catch(IOException e)
{
e.printStackTrace();
}
}
Does anyone know the strategy to add the sheet values into the request arraylist?
The function calls were actually available after creating a new constructor for DimensionRange.
Simply do:
dimensionRange.setDimension("ROWS");
dimensionRange.setSheetId(XXXXX);
to finish the JSON post request to Sheets API...
I am inserting data into a spreadsheet with the new Google Sheets API v4, the code works perfect and the data it is inserted well in the sheet.
But how to find out the last row with data to add the data after this ?
List<List<Object>> arrData = getData();
ValueRange oRange = new ValueRange();
oRange.setRange("Pedidos!AXXXXXXX"); // I NEED THE NUMBER OF THE LAST ROW
oRange.setValues(arrData);
List<ValueRange> oList = new ArrayList<>();
oList.add(oRange);
BatchUpdateValuesRequest oRequest = new BatchUpdateValuesRequest();
oRequest.setValueInputOption("RAW");
oRequest.setData(oList);
BatchUpdateValuesResponse oResp1 = mService.spreadsheets().values().batchUpdate("ID_SPREADSHEET", oRequest).execute();
Is there some trick in the A1 notation for this?
I need an equivalent to .getLastRow from Google Apps Script.
If you use the append feature and set the range to the entire sheet, the API will find the last row and append the new data after it.
This web page explains it.
https://developers.google.com/sheets/api/guides/values#appending_values
Here is some sample code:
String range="Sheet1";
insertData.setValues(rows);
AppendValuesResponse response=service.spreadsheets().values()
.append(spreadsheetId,range,insertData).setValueInputOption("USER_ENTERED")
.execute();
Note that the response will tell you where it was inserted.
The v4 API has no way to ask "what is the last row with data", as it's a different style of API than the Apps Script API. You can infer the last row yourself by requesting the data and counting the offset from your first requested row to the last returned row.
You can use AppendCellsRequest to append a row. The below methods should get you going. I haven't included the getRowDataListForCellStrings method as it is rather application specific.
First create a Request object containing a AppendCellsRequest:
public BatchUpdateSpreadsheetResponse appendWorksheet(String cellValues) throws SpreadsheetException {
AppendCellsRequest appendRequest = new AppendCellsRequest();
appendRequest.setSheetId( mSheet.getProperties().getSheetId() );
appendRequest.setRows( getRowDataListForCellStrings(cellValues) );
appendRequest.setFields("userEnteredValue");
Request req = new Request();
req.setAppendCells( appendRequest );
return executeBatchRequest(req);
}
Then call batchUpdate on the spreadsheets() interface:
BatchUpdateSpreadsheetResponse executeBatchRequest(Request request) throws SpreadsheetException {
List<Request> requests = new ArrayList<>();
requests.add( request );
BatchUpdateSpreadsheetRequest batchRequest = new BatchUpdateSpreadsheetRequest();
batchRequest.setRequests( requests );
try {
return mService.spreadsheets().batchUpdate(mSpreadsheet.getSpreadsheetId(), batchRequest).execute();
} catch (IOException e) {
throw new SpreadsheetException(e);
}
}
Unfortunately there doesn't seem to be a way to know which rows were updated. Not does is seem possible to set valueInputOption when appending in this way.
There is actually a way to ask the API.
I am using this on my node.js client (pretty sure it's very similar)
var sheets = google.sheets('v4');
sheets.spreadsheets.get({
auth: auth,
spreadsheetId: 'spreadsheet_id',
includeGridData: true
}, function (err, response) {
if (err) {
console.log('The API returned an error: ' + err);
} else {
var last_row = response.sheets[0].data[0].rowData.length;
}
});
I am using Android Market api.
I use it to retrieve all the comments to my app:
http://code.google.com/p/android-market-api/wiki/HowToGetAppComments
My question is how can I know what is the authorId of the current user?
I just need to know if that user already write a comment or not.
Thanks!
The example code at the link you posted shows this:
public void onResult(ResponseContext context, CommentsResponse response)
{
System.out.println("Response : " + response);
// response.getComments(0).getAuthorName()
// response.getComments(0).getCreationTime()
// ...
}
Based on the source code , to get theauthorID of the first comment for example, you should be able to use
String id = response.getComments(0).getAuthorID();