ArcGIS version 100.3.0 android token - arcgis-runtime

Below is the code I'm using for setting user credentials on ServiceFeatureTable.
ServiceFeatureTable featureTablePolygons = new ServiceFeatureTable(polygonUrl);
featureTablePolygons.setCredential(UserCredential.createFromToken(gisToken, referer));
//query feature from the table
final ListenableFuture<FeatureQueryResult> queryResultPolygons = featureTablePolygons.queryFeaturesAsync(query);
queryResultPolygons.addDoneListener(() -> {
try {
FeatureCollection featureCollection = new FeatureCollection();
FeatureQueryResult result = queryResultPolygons.get();
FeatureCollectionTable featureCollectionTable = new FeatureCollectionTable(result);
featureCollectionTable.setRenderer(new SimpleRenderer(new SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, getResources().getColor(R.color.translucent_red), new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.RED, 1))));
featureCollection.getTables().add(featureCollectionTable);
FeatureCollectionLayer featureCollectionLayer = new FeatureCollectionLayer(featureCollection);
mMapView.getMap().getOperationalLayers().add(featureCollectionLayer);
if (result.iterator().hasNext()) {
Feature feature = result.iterator().next();
Envelope envelope = feature.getGeometry().getExtent();
mMapView.setViewpointGeometryAsync(envelope);
} else {
}
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "Error in FeatureQueryResult: " + e.getMessage());
}
});
But this is not working. If I'm using AuthenticationManager then it's working fine but I don't want to use username and password in my code.

If you're manually getting the token, you can create a UserCredential object using createFromToken() and set it on the ServiceFeatureTable with setCredential().
However, many workflows for getting a token are handled by the Runtime (e.g. username + password, or OAuth via a Portal). Take a look at the AuthenticationManager documentation to get started.
Lastly, I think you'll get more eyes on your questions over at the ArcGIS Runtime SDK for Android forums.

Related

Various errors using VisionServiceClient in XamarinForms

I am trying to create a simple Xamarin forms app which allows the user to browse for or take a photo and have azure cognitive services tag the photo using a custom vision model.
I am unable to get the client to successfully authenticate or find a resource per the error message in the exception produced by the VisionServiceClient. Am I missing something? What would be the correct values to use for the arguments to VisionServiceClient?
All keys have been removed from the below images, they are populated.
Exception thrown in VS2017:
'Microsoft.ProjectOxford.Vision.ClientException' in System.Private.CoreLib.dll
Call to VisionServiceClient:
private const string endpoint = #"https://eastus2.api.cognitive.microsoft.com/vision/prediction/v1.0";
private const string key = "";
VisionServiceClient visionClient = new VisionServiceClient(key, endpoint);
VisualFeature[] features = { VisualFeature.Tags, VisualFeature.Categories, VisualFeature.Description };
try
{
AnalysisResult temp = await visionClient.AnalyzeImageAsync(imageStream,
features.ToList(), null);
return temp;
}
catch(Exception ex)
{
return null;
}
VS Exception Error:
Azure Portal for cognitive services:
Custom Vision Portal:
It looks like you're confusing the Computer Vision and the Custom Vision APIs. You are attempting to use the client SDK for the former using the API key of the latter.
For .NET languages, you'll want the Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction NuGet package.
Your code will end up looking something like this:
ICustomVisionPredictionClient client = new CustomVisionPredictionClient()
{
ApiKey = PredictionKey,
Endpoint = "https://southcentralus.api.cognitive.microsoft.com"
};
ImagePrediction prediction = await client.PredictImageAsync(ProjectId, stream, IterationId);
Thank you to cthrash for the extended help and talking with me in chat. Using his post along with a little troubleshooting I have figured out what works for me. The code is super clunky but it was just to test and make sure I'm able to do this. To answer the question:
Nuget packages and classes
Using cthrash's post I was able to get both the training and prediction nuget packages installed, which are the correct packages for this particular application. I needed the following classes:
Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction
Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction.Models
Microsoft.Azure.CognitiveServices.Vision.CustomVision.Training
Microsoft.Azure.CognitiveServices.Vision.CustomVision.Training.Models
Endpoint Root
Following some of the steps Here I determined that the endpoint URL's only need to be the root, not the full URL provided in the Custom Vision Portal. For instance,
https://southcentralus.api.cognitive.microsoft.com/customvision/v2.0/Prediction/
Was changed to
https://southcentralus.api.cognitive.microsoft.com
I used both the key and endpoint from the Custom Vision Portal and making that change I was able to use both a training and prediction client to pull the projects and iterations.
Getting Project Id
In order to use CustomVisionPredictionClient.PredictImageAsync you need a Guid for the project id and an iteration id if a default iteration is not set in the portal.
I tested two ways to get the project id,
Using project id string from portal
Grab the project id string from the portal under the project settings.
For the first argument to PredictImageAsync pass
Guid.Parse(projectId)
Using the training client
Create a new CustomVisionTrainingClient
To get a list of <Project> use
TrainingClient.GetProjects().ToList()
In my case I only had a single project so I would just need the first element.
Guid projectId = projects[0].Id
Getting Iteration Id
To get the iteration id of a project you need the CustomVisionTrainingClient.
Create the client
To get a list of <Iteration> use
client.GetIterations(projectId).ToList()
In my case I had only a single iteration so I just need the first element.
Guid iterationId = iterations[0].Id
I am now able to use my model to classify images. In the code below, fileStream is the image stream passed to the model.
public async Task<string> Predict(Stream fileStream)
{
string projectId = "";
//string trainingEndpoint = "https://southcentralus.api.cognitive.microsoft.com/customvision/v2.2/Training/";
string trainingEndpoint = "https://southcentralus.api.cognitive.microsoft.com/";
string trainingKey = "";
//string predictionEndpoint = "https://southcentralus.api.cognitive.microsoft.com/customvision/v2.0/Prediction/";
string predictionEndpoint = "https://southcentralus.api.cognitive.microsoft.com";
string predictionKey = "";
CustomVisionTrainingClient trainingClient = new CustomVisionTrainingClient
{
ApiKey = trainingKey,
Endpoint = trainingEndpoint
};
List<Project> projects = new List<Project>();
try
{
projects = trainingClient.GetProjects().ToList();
}
catch(Exception ex)
{
Debug.WriteLine("Unable to get projects:\n\n" + ex.Message);
return "Unable to obtain projects.";
}
Guid ProjectId = Guid.Empty;
if(projects.Count > 0)
{
ProjectId = projects[0].Id;
}
if (ProjectId == Guid.Empty)
{
Debug.WriteLine("Unable to obtain project ID");
return "Unable to obtain project id.";
}
List<Iteration> iterations = new List<Iteration>();
try
{
iterations = trainingClient.GetIterations(ProjectId).ToList();
}
catch(Exception ex)
{
Debug.WriteLine("Unable to obtain iterations.");
return "Unable to obtain iterations.";
}
foreach(Iteration itr in iterations)
{
Debug.WriteLine(itr.Name + "\t" + itr.Id + "\n");
}
Guid iteration = Guid.Empty;
if(iterations.Count > 0)
{
iteration = iterations[0].Id;
}
if(iteration == Guid.Empty)
{
Debug.WriteLine("Unable to obtain project iteration.");
return "Unable to obtain project iteration";
}
CustomVisionPredictionClient predictionClient = new CustomVisionPredictionClient
{
ApiKey = predictionKey,
Endpoint = predictionEndpoint
};
var result = await predictionClient.PredictImageAsync(Guid.Parse(projectId), fileStream, iteration);
string resultStr = string.Empty;
foreach(PredictionModel pred in result.Predictions)
{
if(pred.Probability >= 0.85)
resultStr += pred.TagName + " ";
}
return resultStr;
}

Xamarin Auth account store

I'm trying to implement Xamairn Auth with my app. I've installed the nuget package from https://www.nuget.org/packages/Xamarin.Auth.
Following their example I have the following code in the shared project.
public void SaveCredentials (string userName, string password)
{
if (!string.IsNullOrWhiteSpace (userName) && !string.IsNullOrWhiteSpace (password)) {
Account account = new Account {
Username = userName
};
account.Properties.Add ("Password", password);
AccountStore.Create ().Save (account, App.AppName);
}
}
When run on android, it saves the username and password but I'm getting the following message in the console:
"This version is insecure, because of default password.
Please use version with supplied password for AccountStore.
AccountStore.Create(Contex, string) or AccountStore.Create(string);"
I tried passing a parameter to the AccountStore.Create() method but it doesn't seem to take one. Something like this:
#if ANDROID
_accountStore = AccountStore.Create(Application.Context);
#else
_accountStore = AccountStore.Create();
#endif
Do I need to write android specific code to extend the create method.
I understand why you deleted the non-answer, I thought that would show interest in the question. I guess I should have upvoted the question instead. Anyways, here's the answer I found.
You can't use the PCL version for android. It doesn't have an option to add a password. I used the android specific version. Will call it using dependency service.
Here's an example:
Account account = null;
try
{
//account = AccountStore.Create(Application.ApplicationContext, "System.Char[]").FindAccountsForService("My APP").FirstOrDefault();
var aStore = AccountStore.Create(Application.ApplicationContext, "myownpassword");
// save test
account = aStore.FindAccountsForService(Constants.AppName).FirstOrDefault();
if (account == null)
account = new Account();
account.Username = "bobbafett";
account.Properties["pswd"] = "haha";
aStore.Save(account, Constants.AppName);
// delete test, doesn't seem to work, account is still found
var accts = aStore.FindAccountsForService(Constants.AppName);
int howMany = accts.ToList().Count;
foreach (var acct in accts)
{
aStore.Delete(acct, Constants.AppName);
}
account = aStore.FindAccountsForService(Constants.AppName).FirstOrDefault();
}
catch (Java.IO.IOException ex)
{
// This part is not invoked anymore once I use the suggested password.
int i1 = 123;
}
I was able to get it to work by implementing a getAccountStore method in android which has an option to add a password, then use DependencyService to call it.
public AccountStore GetAccountStore()
{
try
{
var acctStore = AccountStore.Create(Application.Context, "somePassword");
return acctStore;
}
catch (Java.IO.IOException ex)
{
throw ex;
}
}
Then in your pcl project call it as such:
if (Device.RuntimePlatform == Device.Android)
_accountStore = DependencyService.Get<IAccountStoreHelper>().GetAccountStore();
else
_accountStore = AccountStore.Create();

System.MissingMethodException Method 'System.Net.Http.HttpClientHandler.set_Proxy' not found

This is a Xamarin solution and I am getting the error found in this message's title. Of course, I can easily confirm that there is a Proxy property on HttpClientHandler in the PCL project. And the solution builds without error. Only when I run does it produce this error (on either Droid or iOS) and does so at the point where it invokes the method in the PCL which instantiates the HttpClient. Note that it doesn't even get to that method. The error appears on the application start-up method; e.g., UIApplication.Main()
If I comment out the handler and instantiate HttpClient without a handler, it works fine as long as I'm on the open internet. But I'm trying to get this to work from behind a proxy.
Further investigation showed that the device projects had no references to System.Net.Http. So I added these -- and it indicates Xamarin.iOS and Xamarin.Android as the packages -- but it still produces the error.
I'm not clear what the error is telling me but I believe it means that the device project can't see System.Net.Http.HttpClientHandler?
private HttpClient GetHttpClient()
{
WebProxy proxy = new WebProxy(ProxyConfig.Url)
{
Credentials = new NetworkCredential(ProxyConfig.Username, ProxyConfig.Password)
};
// At runtime, when GetHttpClient is invoked, it says it cannot find the Proxy setter
HttpClientHandler handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true,
PreAuthenticate = true,
UseDefaultCredentials = false,
};
HttpClient client = new HttpClient(handler);
// This works when not behind a proxy
//HttpClient client = new HttpClient();
return client;
}
public async Task GetWeatherAsync(double longitude, double latitude, string username)
{
// MissingMethodException is thrown at this point
var client = GetHttpClient();
client.BaseAddress = new Uri(string.Format("http://api.geonames.org/findNearByWeatherJSON?lat={0}&lng={1}&username={2}", latitude, longitude, username));
try
{
var response = await client.GetAsync(client.BaseAddress);
if (response.IsSuccessStatusCode)
{
var JsonResult = response.Content.ReadAsStringAsync().Result;
var weather = JsonConvert.DeserializeObject<WeatherResult>(JsonResult);
SetValues(weather);
}
else
{
Debug.WriteLine(response.RequestMessage);
}
}
catch (HttpRequestException ex)
{
Debug.WriteLine(ex.Message);
}
catch (System.Net.WebException ex)
{
Debug.WriteLine(ex.Message);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
Add the Microsoft.Net.Http NuGet package to your platform project too. If you run into an issue adding this, try installing the latest Microsoft.Bcl.Build package first. Then, after that is installed, add the HTTP package.

Google Places API in Android gives Place StatusCode as PLACES_API_USAGE_LIMIT_EXCEEDED

I have used Google Places API for adding the place. Below is the code for GoogleApiClient and Adding a Place.
Start indented code:
mGoogleApiClient = new GoogleApiClient
.Builder(this)
.enableAutoManage(this, 0, this)
.addApi(Places.GEO_DATA_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
AddPlaceRequest place =
new AddPlaceRequest(
"xyz",
new LatLng(point.latitude, point.longitude),
"2095",
Collections.singletonList(Place.TYPE_SHOE_STORE),
"+123456789",
Uri.parse("www.abc.com/")
);
Places.GeoDataApi.addPlace(mGoogleApiClient, place).setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
final Place place = places.get(0);
Log.i(TAG, "Place add result: " + place.getName());
places.release();
}
});
I am getting Output as :
Place query did not complete. Error:
Status{statusCode=PLACES_API_USAGE_LIMIT_EXCEEDED, resolution=null}
I have not even requested more than 25 times for Google Places API. Even if I try from different account also it gives me the same error. Thanks in advance.

How to programmatically get provisioning resources with oim 11g client api

I'm using the oracle OIM 11g api (in packages oracle.iam). I use the class oracle.iam.platform.OIMClient to get all the OIM client services like UserManager.
I need to find the resources got with the provisioning workflows. Which service can I use? How can I do with the OIM api?
The method below should export all resources into an XML file-
public Boolean export() {
Boolean result = true;
String export_object="Resource";
try {
FileWriter fstream = new FileWriter("OIMResources.xml");
BufferedWriter out = new BufferedWriter(fstream);
tcExportOperationsIntf moExportUtility = (tcExportOperationsIntf) ioUtilityFactory.getUtility("Thor.API.Operations.tcExportOperationsIntf");
Collection<RootObject> lstObjects = moExportUtility.findObjects(export_object, "*");
System.out.println(lstObjects);
lstObjects.addAll(moExportUtility.getDependencies(lstObjects));
lstObjects.addAll(moExportUtility.retrieveChildren(lstObjects));
lstObjects.addAll(moExportUtility.retrieveDependencyTree(lstObjects));
String s = moExportUtility.getExportXML(lstObjects, "*");
out.write(s);
LOG.info(Resource + "Objects successfully exported");
out.close();
} catch (Exception e) {
LOG.log(Level.SEVERE, "Exception occured while exporting OIM object" + Resource, e);
}
return result;
}

Resources