I'm developing a Jenkins plugin and in one of my build steps, I need to return a value. In this build step, I'm sending an API call to generate a registration token and I want to return that token as the output of this build step. The idea is to use this generated token later in pipeline/free-style.
My question is, how do I do that?
Here's my Build class:
package **.********.plugins;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.*;
import hudson.tasks.BuildStep;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Builder;
import hudson.util.ListBoxModel;
import **.********.constants.Constants;
import **.********.helpers.ApiHelper;
import **.********.helpers.ApiResponse;
import **.********.helpers.LogHelper;
import **.********.model.AgentDockerConfigData;
import **.********.model.AgentDockerConfigGenerationRequestData;
import **.********.model.JobData;
import **.********.model.ProjectData;
import jenkins.tasks.SimpleBuildStep;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.HashMap;
public class GenerateAgentConfigToken extends Builder implements SimpleBuildStep {
//region Private members
private ApiHelper apiHelper;
private String alias;
private String projectId;
private String jobId;
private String browsers;
private AgentDockerConfigData config;
//endregion
//region Constructors
public GenerateAgentConfigToken() { }
#DataBoundConstructor
public GenerateAgentConfigToken(String alias, String projectId, String jobId, String browsers) {
this.alias = alias;
this.projectId = projectId;
this.jobId = jobId;
this.browsers = browsers;
}
//endregion
//region Setters & Getters
public String getAlias() {
return alias;
}
#DataBoundSetter
public void setAlias(String alias) {
this.alias = alias;
}
public String getProjectId() {
return projectId;
}
#DataBoundSetter
public void setProjectId(String projectId) {
this.projectId = projectId;
}
public String getJobId() {
return jobId;
}
#DataBoundSetter
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getBrowsers() {
return browsers;
}
#DataBoundSetter
public void setBrowsers(String browsers) {
this.browsers = browsers;
}
//endregion
private void init() {
LogHelper.Debug("Initializing API helper...");
this.apiHelper = new ApiHelper(PluginConfiguration.DESCRIPTOR.getApiKey());
}
#Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
#Override
public void perform(#Nonnull Run<?, ?> run, #Nonnull FilePath filePath, #Nonnull Launcher launcher, #Nonnull TaskListener taskListener) throws InterruptedException, IOException {
try {
EnvVars envVars = new EnvVars();
envVars = run.getEnvironment(taskListener);
envVars.put("jobId", jobId);
init();
LogHelper.SetLogger(taskListener.getLogger(), PluginConfiguration.DESCRIPTOR.isVerbose());
generateAgentConfigToken();
} catch (Exception e) {
LogHelper.Error(e);
run.setResult(Result.FAILURE);
}
}
private void generateAgentConfigToken() throws IOException {
LogHelper.Info("Sending a request to generate agent configuration token...");
//TODO: Change the URL to the production URL
ApiResponse<AgentDockerConfigData> response = apiHelper.Post(
Constants.TP_GENERATE_AGENT_CONFIG_TOKEN_URL,
null,
null,
generateRequestBody(),
AgentDockerConfigData.class);
if (response.isSuccessful()) {
if (response.getData() != null) {
config = response.getData();
}
} else {
int statusCode = response.getStatusCode();
String responseMessage = response.getMessage();
String message = "Unable to generate agent configuration token" + (statusCode > 0 ? " - " + statusCode : "") + (responseMessage != null ? " - " + responseMessage : "");
throw new hudson.AbortException(message);
}
}
private AgentDockerConfigGenerationRequestData generateRequestBody() {
// if the user did not provide an alias and jobId, send the body as null
if (StringUtils.isEmpty(alias) && StringUtils.isEmpty(jobId))
return null;
AgentDockerConfigGenerationRequestData body = new AgentDockerConfigGenerationRequestData();
if (!StringUtils.isEmpty(alias))
body.setAlias(alias);
if (!StringUtils.isEmpty(jobId)) {
body.setJobId(jobId);
if (!StringUtils.isEmpty(browsers))
body.setBrowsers(browsers.split(","));
}
return body;
}
#Override
public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); }
#Extension
#Symbol(Constants.TP_GENERATE_AGENT_CONFIG_TOKEN_SYMBOL)
public static class DescriptorImpl extends BuildStepDescriptor<Builder> {
public DescriptorImpl() {
load();
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req, formData);
}
#Override
public boolean isApplicable(#SuppressWarnings("rawtypes") Class<? extends AbstractProject> jobType) {
return true;
}
#Nonnull
#Override
public String getDisplayName() {
return Constants.TP_GENERATE_AGENT_CONFIG_TOKEN;
}
public ListBoxModel doFillProjectIdItems() {
HashMap<String, Object> headers = new HashMap<>();
headers.put(Constants.ACCEPT, Constants.APPLICATION_JSON);
ApiResponse<ProjectData[]> response = null;
try {
ApiHelper apiHelper = new ApiHelper(PluginConfiguration.DESCRIPTOR.getApiKey());
response = apiHelper.Get(Constants.TP_RETURN_ACCOUNT_PROJECTS, headers, ProjectData[].class);
if (!response.isSuccessful()) {
int statusCode = response.getStatusCode();
String responseMessage = response.getMessage();
String message = "Unable to fetch the projects list" + (statusCode > 0 ? " - " + statusCode : "") + (responseMessage != null ? " - " + responseMessage : "");
throw new hudson.AbortException(message);
}
ListBoxModel model = new ListBoxModel();
model.add("Select a project", "");
for (ProjectData project : response.getData()) {
model.add(
project.getName() + " [" + project.getId() + "]",
project.getId());
}
return model;
} catch (IOException | NullPointerException e) {
LogHelper.Error(e);
}
return null;
}
public ListBoxModel doFillJobIdItems(#QueryParameter String projectId) {
if (projectId.isEmpty()) {
return new ListBoxModel();
}
HashMap<String, Object> headers = new HashMap<>();
headers.put(Constants.ACCEPT, Constants.APPLICATION_JSON);
ApiResponse<JobData[]> response = null;
try {
ApiHelper apiHelper = new ApiHelper(PluginConfiguration.DESCRIPTOR.getApiKey());
response = apiHelper.Get(String.format(Constants.TP_RETURN_PROJECT_JOBS, projectId), headers, JobData[].class);
if (!response.isSuccessful()) {
int statusCode = response.getStatusCode();
String responseMessage = response.getMessage();
String message = "Unable to fetch the project's jobs list" + (statusCode > 0 ? " - " + statusCode : "") + (responseMessage != null ? " - " + responseMessage : "");
throw new hudson.AbortException(message);
}
ListBoxModel model = new ListBoxModel();
model.add("Select a job to execute from the selected project (You must select a project first)", "");
for (JobData job : response.getData()) {
model.add(
job.getName() + " [" + job.getId() + "]",
job.getId());
}
return model;
} catch (IOException | NullPointerException e) {
LogHelper.Error(e);
}
return null;
}
}
}
Is there a way to return anything from perform rather than void or boolean ?
Related
I exposed Rest APIs, and I generated client code using Swagger 2 Java language with Feign library. The code gen generated the below OAuth RequestInterceptor. I am getting the below error when I use the oAuth as auth.
Error
feign.RetryableException: url values must be not be absolute.
at com.sam.feign.auth.OAuth.updateAccessToken(OAuth.java:95)
at com.sam.feign.auth.OAuth.apply(OAuth.java:83)
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:161)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
at com.sun.proxy.$Proxy9.getUser(Unknown Source)
at com.sam.feign.clients.UserApiTest.getUserTest(UserApiTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalArgumentException: url values must be not be absolute.
at feign.RequestTemplate.uri(RequestTemplate.java:434)
at feign.RequestTemplate.uri(RequestTemplate.java:421)
at feign.RequestTemplate.append(RequestTemplate.java:388)
at com.sam.feign.auth.OAuth$OAuthFeignClient.execute(OAuth.java:163)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:65)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:55)
at org.apache.oltu.oauth2.client.OAuthClient.accessToken(OAuthClient.java:71)
at com.sam.feign.auth.OAuth.updateAccessToken(OAuth.java:93)
... 34 more
Swagger Generated oAuth supporting file
public class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener {
void notify(BasicOAuthToken token);
}
private volatile String accessToken;
private Long expirationTimeMillis;
private OAuthClient oauthClient;
private TokenRequestBuilder tokenRequestBuilder;
private AuthenticationRequestBuilder authenticationRequestBuilder;
private AccessTokenListener accessTokenListener;
public OAuth(Client client, TokenRequestBuilder requestBuilder) {
this.oauthClient = new OAuthClient(new OAuthFeignClient(client));
this.tokenRequestBuilder = requestBuilder;
}
public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes));
switch(flow) {
case accessCode:
case implicit:
tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
break;
case password:
tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
break;
case application:
tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
break;
default:
break;
}
authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
}
#Override
public void apply(RequestTemplate template) {
// If the request already have an authorization (eg. Basic auth), do nothing
if (template.headers().containsKey("Authorization")) {
return;
}
// If first time, get the token
if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
updateAccessToken(template);
}
if (getAccessToken() != null) {
template.header("Authorization", "Bearer " + getAccessToken());
}
}
public synchronized void updateAccessToken(RequestTemplate template) {
OAuthJSONAccessTokenResponse accessTokenResponse;
try {
accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
} catch (Exception e) {
throw new RetryableException(400, e.getMessage(), template.request().httpMethod(), e, null, template.request());
}
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn());
if (accessTokenListener != null) {
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
}
}
}
public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
public synchronized String getAccessToken() {
return accessToken;
}
public synchronized void setAccessToken(String accessToken, Long expiresIn) {
this.accessToken = accessToken;
this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
public AuthenticationRequestBuilder getAuthenticationRequestBuilder() {
return authenticationRequestBuilder;
}
public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) {
this.authenticationRequestBuilder = authenticationRequestBuilder;
}
public OAuthClient getOauthClient() {
return oauthClient;
}
public void setOauthClient(OAuthClient oauthClient) {
this.oauthClient = oauthClient;
}
public void setOauthClient(Client client) {
this.oauthClient = new OAuthClient( new OAuthFeignClient(client));
}
public static class OAuthFeignClient implements HttpClient {
private Client client;
public OAuthFeignClient() {
this.client = new Client.Default(null, null);
}
public OAuthFeignClient(Client client) {
this.client = client;
}
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
RequestTemplate req = new RequestTemplate()
.append(request.getLocationUri())
.method(requestMethod)
.body(request.getBody());
for (Entry<String, String> entry : headers.entrySet()) {
req.header(entry.getKey(), entry.getValue());
}
Response feignResponse;
String body = "";
try {
feignResponse = client.execute(req.request(), new Options());
body = Util.toString(feignResponse.body().asReader());
} catch (IOException e) {
throw new OAuthSystemException(e);
}
String contentType = null;
Collection<String> contentTypeHeader = feignResponse.headers().get("Content-Type");
if(contentTypeHeader != null) {
contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";");
}
return OAuthClientResponseFactory.createCustomResponse(
body,
contentType,
feignResponse.status(),
responseClass
);
}
public void shutdown() {
// Nothing to do here
}
}
}
ApiClient.java have the below absolute URL which configured in swagger spec
public ApiClient() {
objectMapper = createObjectMapper();
apiAuthorizations = new LinkedHashMap<String, RequestInterceptor>();
feignBuilder = Feign.builder()
.encoder(new FormEncoder(new JacksonEncoder(objectMapper)))
.decoder(new JacksonDecoder(objectMapper))
.logger(new Slf4jLogger());
}
public ApiClient(String[] authNames) {
this();
for(String authName : authNames) {
RequestInterceptor auth = null;
if ("client-credentils-oauth2".equals(authName)) {
auth = new OAuth(OAuthFlow.application, "", "http://localhost:8080/app/oauth/token", "user.create");
} else if ("password-oauth2".equals(authName)) {
auth = new OAuth(OAuthFlow.password, "", "http://localhost:8080/app/oauth/token", "openid");
} else {
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
}
addAuthorization(authName, auth);
}
}
Used the below dependencies
swagger-codegen-maven-plugin v2.4.28
feign-version 11.6
feign-form-version 3.8.0
oltu-version 1.0.1
Java 8
I am invoking the client by using below code
UserApi api = new ApiClient("client-credentils-oauth2","admin", "admin", null, null).buildClient(UserApi.class);
api.getUser(login, tenant)
I made the few changes in the generated oAuth.java file to make it work. Expecting the client generated code should work without making any manual changes.
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
// Added the below 3 lines
URI targetUri = URI.create(uri);
String target = targetUri.getScheme() + "://" + targetUri.getAuthority() ;
String path = targetUri.getPath();
RequestTemplate req = new RequestTemplate()
.uri(path)
.method(requestMethod)
.body(request.getBody())
.target(target); // Added this line
for (Entry<String, String> entry : headers.entrySet()) {
req.header(entry.getKey(), entry.getValue());
}
req = req.resolve(new HashMap<String, Object>()); // Added this line
Response feignResponse;
String body = "";
try {
feignResponse = client.execute(req.request(), new Options());
body = Util.toString(feignResponse.body().asReader());
} catch (IOException e) {
throw new OAuthSystemException(e);
}
String contentType = null;
Collection<String> contentTypeHeader = feignResponse.headers().get("Content-Type");
if(contentTypeHeader != null) {
contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";");
}
return OAuthClientResponseFactory.createCustomResponse(
body,
contentType,
feignResponse.status(),
responseClass
);
}
Appreciate if someone can assist me with this issue
I'm a student doing an Android Things project, which is about connecting Rasperi pi with an Accelerometer sensor to get acceleration data, I finished the coding part in Android Studio and the sensor is working fine, then I tried to connect my project to the cloud by following this tutorial: http://blog.blundellapps.co.uk/tut-google-cloud-iot-core-mqtt-on-android/
I think I have to publish the accelerometer data to the cloud by calling this method below in MainActivity class, I did that but still have an error, see the update I did at end of this question please.
#Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "Accel X " + event.values[0]);
Log.d(TAG, "Accel Y " + event.values[1]);
Log.d(TAG, "Accel Z " + event.values[2]);
}
Also, do I have to do something in the cloud platform to receive the data?, I already set up the communication with my Google IoT Core details as shown in the below code:
communicator = new IotCoreCommunicator.Builder()
.withContext(this)
.withCloudRegion("us-central1")
.withProjectId("my-first-project-198704")
.withRegistryId("vibration")
.withDeviceId("my-device")
.withPrivateKeyRawFileId(R.raw.rsa_private)
.build();
This is what I'm seeing in the cloud:
And this is the acceleration data I have in Android Studio:
My project consists of two modules but here I will attach only the second module because the question is limited to 3000 characters only and the second module is what I need to edit I think.
sample module:
AccelerometerActivity class:
package com.cacaosd.sample;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import com.cacaosd.adxl345.ADXL345SensorDriver;
import com.cacaosd.sample.BoardDefaults;
import java.io.IOException;
public class AccelerometerActivity extends Activity implements SensorEventListener {
private static final String TAG = AccelerometerActivity.class.getSimpleName();
private ADXL345SensorDriver mSensorDriver;
private SensorManager mSensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerDynamicSensorCallback(new SensorManager.DynamicSensorCallback() {
#Override
public void onDynamicSensorConnected(Sensor sensor) {
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mSensorManager.registerListener(AccelerometerActivity.this,
sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
});
try {
mSensorDriver = new ADXL345SensorDriver(BoardDefaults.getI2CPort());
mSensorDriver.registerAccelerometerSensor();
} catch (IOException e) {
Log.e(TAG, "Error configuring sensor", e);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "Closing sensor");
if (mSensorDriver != null) {
mSensorManager.unregisterListener(this);
try {
mSensorDriver.close();
} catch (IOException e) {
Log.e(TAG, "Error closing sensor", e);
} catch (Exception e) {
e.printStackTrace();
} finally {
mSensorDriver = null;
}
}
}
#Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "Accel X " + event.values[0]);
Log.d(TAG, "Accel Y " + event.values[1]);
Log.d(TAG, "Accel Z " + event.values[2]);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
Log.i(TAG, "sensor accuracy changed: " + accuracy);
}
}
BoardDefaults class:
package com.cacaosd.sample;
import android.os.Build;
import com.google.android.things.pio.PeripheralManagerService;
import java.util.List;
/**
* Created by cagdas on 20.12.2016.
*/
#SuppressWarnings("WeakerAccess")
public class BoardDefaults {
private static final String DEVICE_EDISON_ARDUINO = "edison_arduino";
private static final String DEVICE_EDISON = "edison";
private static final String DEVICE_RPI3 = "rpi3";
private static final String DEVICE_NXP = "imx6ul";
private static String sBoardVariant = "";
/**
* Return the preferred I2C port for each board.
*/
public static String getI2CPort() {
switch (getBoardVariant()) {
case DEVICE_EDISON_ARDUINO:
return "I2C6";
case DEVICE_EDISON:
return "I2C1";
case DEVICE_RPI3:
return "I2C1";
case DEVICE_NXP:
return "I2C2";
default:
throw new IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE);
}
}
private static String getBoardVariant() {
if (!sBoardVariant.isEmpty()) {
return sBoardVariant;
}
sBoardVariant = Build.DEVICE;
// For the edison check the pin prefix
// to always return Edison Breakout pin name when applicable.
if (sBoardVariant.equals(DEVICE_EDISON)) {
PeripheralManagerService pioService = new PeripheralManagerService();
List<String> gpioList = pioService.getGpioList();
if (gpioList.size() != 0) {
String pin = gpioList.get(0);
if (pin.startsWith("IO")) {
sBoardVariant = DEVICE_EDISON_ARDUINO;
}
}
}
return sBoardVariant;
}
}
IotCoreCommunicator class:
package com.cacaosd.sample1;
import android.content.Context;
import android.util.Log;
import java.util.concurrent.TimeUnit;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class IotCoreCommunicator {
private static final String SERVER_URI = "ssl://mqtt.googleapis.com:8883";
public static class Builder {
private Context context;
private String projectId;
private String cloudRegion;
private String registryId;
private String deviceId;
private int privateKeyRawFileId;
public Builder withContext(Context context) {
this.context = context;
return this;
}
public Builder withProjectId(String projectId) {
this.projectId = projectId;
return this;
}
public Builder withCloudRegion(String cloudRegion) {
this.cloudRegion = cloudRegion;
return this;
}
public Builder withRegistryId(String registryId) {
this.registryId = registryId;
return this;
}
public Builder withDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public Builder withPrivateKeyRawFileId(int privateKeyRawFileId) {
this.privateKeyRawFileId = privateKeyRawFileId;
return this;
}
public IotCoreCommunicator build() {
if (context == null) {
throw new IllegalStateException("context must not be null");
}
if (projectId == null) {
throw new IllegalStateException("projectId must not be null");
}
if (cloudRegion == null) {
throw new IllegalStateException("cloudRegion must not be null");
}
if (registryId == null) {
throw new IllegalStateException("registryId must not be null");
}
if (deviceId == null) {
throw new IllegalStateException("deviceId must not be null");
}
String clientId = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + registryId + "/devices/" + deviceId;
if (privateKeyRawFileId == 0) {
throw new IllegalStateException("privateKeyRawFileId must not be 0");
}
MqttAndroidClient client = new MqttAndroidClient(context, SERVER_URI, clientId);
IotCorePasswordGenerator passwordGenerator = new IotCorePasswordGenerator(projectId, context.getResources(), privateKeyRawFileId);
return new IotCoreCommunicator(client, deviceId, passwordGenerator);
}
}
private final MqttAndroidClient client;
private final String deviceId;
private final IotCorePasswordGenerator passwordGenerator;
IotCoreCommunicator(MqttAndroidClient client, String deviceId, IotCorePasswordGenerator passwordGenerator) {
this.client = client;
this.deviceId = deviceId;
this.passwordGenerator = passwordGenerator;
}
public void connect() {
monitorConnection();
clientConnect();
subscribeToConfigChanges();
}
private void monitorConnection() {
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
Log.e("TUT", "connection lost", cause);
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d("TUT", "message arrived " + topic + " MSG " + message);
// You need to do something with messages when they arrive
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.d("TUT", "delivery complete " + token);
}
});
}
private void clientConnect() {
try {
MqttConnectOptions connectOptions = new MqttConnectOptions();
// Note that the the Google Cloud IoT Core only supports MQTT 3.1.1, and Paho requires that we explicitly set this.
// If you don't, the server will immediately close its connection to your device.
connectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
// With Google Cloud IoT Core, the username field is ignored, however it must be set for the
// Paho client library to send the password field. The password field is used to transmit a JWT to authorize the device.
connectOptions.setUserName("unused-but-necessary");
connectOptions.setPassword(passwordGenerator.createJwtRsaPassword());
IMqttToken iMqttToken = client.connect(connectOptions);
iMqttToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.d("TUT", "success, connected");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e("TUT", "failure, not connected", exception);
}
});
iMqttToken.waitForCompletion(TimeUnit.SECONDS.toMillis(30));
Log.d("TUT", "IoT Core connection established.");
} catch (MqttException e) {
throw new IllegalStateException(e);
}
}
/**
* Configuration is managed and sent from the IoT Core Platform
*/
private void subscribeToConfigChanges() {
try {
client.subscribe("/devices/" + deviceId + "/config", 1);
} catch (MqttException e) {
throw new IllegalStateException(e);
}
}
public void publishMessage(String subtopic, String message) {
String topic = "/devices/" + deviceId + "/" + subtopic;
String payload = "{msg:\"" + message + "\"}";
MqttMessage mqttMessage = new MqttMessage(payload.getBytes());
mqttMessage.setQos(1);
try {
client.publish(topic, mqttMessage);
Log.d("TUT", "IoT Core message published. To topic: " + topic);
} catch (MqttException e) {
throw new IllegalStateException(e);
}
}
public void disconnect() {
try {
Log.d("TUT", "IoT Core connection disconnected.");
client.disconnect();
} catch (MqttException e) {
throw new IllegalStateException(e);
}
}
}
IotCorePasswordGenerator class:
package com.cacaosd.sample1;
import android.content.res.Resources;
import android.util.Base64;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
class IotCorePasswordGenerator {
private final String projectId;
private final Resources resources;
private final int privateKeyRawFileId;
IotCorePasswordGenerator(String projectId, Resources resources, int privateKeyRawFileId) {
this.projectId = projectId;
this.resources = resources;
this.privateKeyRawFileId = privateKeyRawFileId;
}
char[] createJwtRsaPassword() {
try {
byte[] privateKeyBytes = decodePrivateKey(resources, privateKeyRawFileId);
return createJwtRsaPassword(projectId, privateKeyBytes).toCharArray();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("Algorithm not supported. (developer error)", e);
} catch (InvalidKeySpecException e) {
throw new IllegalStateException("Invalid Key spec. (developer error)", e);
} catch (IOException e) {
throw new IllegalStateException("Cannot read private key file.", e);
}
}
private static byte[] decodePrivateKey(Resources resources, int privateKeyRawFileId) throws IOException {
try(InputStream inStream = resources.openRawResource(privateKeyRawFileId)) {
return Base64.decode(inputToString(inStream), Base64.DEFAULT);
}
}
private static String inputToString(InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
private static String createJwtRsaPassword(String projectId, byte[] privateKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
return createPassword(projectId, privateKeyBytes, "RSA", SignatureAlgorithm.RS256);
}
private static String createPassword(String projectId, byte[] privateKeyBytes, String algorithmName, SignatureAlgorithm signatureAlgorithm) throws NoSuchAlgorithmException, InvalidKeySpecException {
Instant now = Instant.now();
// Create a JWT to authenticate this device. The device will be disconnected after the token
// expires, and will have to reconnect with a new token. The audience field should always be set
// to the GCP project id.
JwtBuilder jwtBuilder =
Jwts.builder()
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(now.plus(Duration.ofMinutes(20))))
.setAudience(projectId);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory kf = KeyFactory.getInstance(algorithmName);
return jwtBuilder.signWith(signatureAlgorithm, kf.generatePrivate(spec)).compact();
}
}
MainActivity class:
package com.cacaosd.sample1;
import android.app.Activity;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import com.cacaosd.sample.AccelerometerActivity;
import com.cacaosd.sample.R;
import com.cacaosd.sample1.IotCoreCommunicator;
import com.google.android.things.pio.Gpio;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity {
AccelerometerActivity mAccelerometerActivity = new AccelerometerActivity();
private IotCoreCommunicator communicator;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the communication with your Google IoT Core details
communicator = new IotCoreCommunicator.Builder()
.withContext(this)
.withCloudRegion("us-central1") // ex: europe-west1
.withProjectId("my-first-project-198704") // ex: supercoolproject23236
.withRegistryId("vibration") // ex: my-devices
.withDeviceId("my-device") // ex: my-test-raspberry-pi
.withPrivateKeyRawFileId(R.raw.rsa_private)
.build();
HandlerThread thread = new HandlerThread("MyBackgroundThread");
thread.start();
handler = new Handler(thread.getLooper());
handler.post(connectOffTheMainThread); // Use whatever threading mechanism you want
}
private final Runnable connectOffTheMainThread = new Runnable() {
#Override
public void run() {
communicator.connect();
handler.post(sendMqttMessage);
}
};
private final Runnable sendMqttMessage = new Runnable() {
private int i;
/**
* We post 100 messages as an example, 1 a second
*/
#Override
public void run() {
if (i == 100) {
return;
}
SensorEvent event = null;
// events is the default topic for MQTT communication
String subtopic = "events";
// Your message you want to send
String message = "Hello World " + i++;
communicator.publishMessage(subtopic, message);
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1));
}
};
#Override
protected void onDestroy() {
communicator.disconnect();
super.onDestroy();
}
MainActivity class:
package com.cacaosd.sample1;
import android.app.Activity;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import com.cacaosd.sample.AccelerometerActivity;
import com.cacaosd.sample.R;
import com.cacaosd.sample1.IotCoreCommunicator;
import com.google.android.things.pio.Gpio;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity {
AccelerometerActivity mAccelerometerActivity = new AccelerometerActivity();
private IotCoreCommunicator communicator;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the communication with your Google IoT Core details
communicator = new IotCoreCommunicator.Builder()
.withContext(this)
.withCloudRegion("us-central1") // ex: europe-west1
.withProjectId("my-first-project-198704") // ex: supercoolproject23236
.withRegistryId("vibration") // ex: my-devices
.withDeviceId("my-device") // ex: my-test-raspberry-pi
.withPrivateKeyRawFileId(R.raw.rsa_private)
.build();
HandlerThread thread = new HandlerThread("MyBackgroundThread");
thread.start();
handler = new Handler(thread.getLooper());
handler.post(connectOffTheMainThread); // Use whatever threading mechanism you want
}
private final Runnable connectOffTheMainThread = new Runnable() {
#Override
public void run() {
communicator.connect();
handler.post(sendMqttMessage);
}
};
private final Runnable sendMqttMessage = new Runnable() {
private int i;
/**
* We post 100 messages as an example, 1 a second
*/
#Override
public void run() {
if (i == 100) {
return;
}
SensorEvent event = null;
// events is the default topic for MQTT communication
String subtopic = "events";
// Your message you want to send
String message = "Hello World " + i++;
communicator.publishMessage(subtopic, message);
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1));
}
};
#Override
protected void onDestroy() {
communicator.disconnect();
super.onDestroy();
}
}
Update:
I added a third input (int acceleration) on publishMessage() method inside IotCoreCommunicator class like below:
public void publishMessage(String subtopic, String message, int acceleration) {
String topic = "/devices/" + deviceId + "/" + subtopic;
String payload = "{msg:\"" + message + "\"}";
MqttMessage mqttMessage = new MqttMessage(payload.getBytes());
mqttMessage.setQos(1);
try {
client.publish(topic, mqttMessage);
Log.d("TUT", "IoT Core message published. To topic: " + topic);
} catch (MqttException e) {
throw new IllegalStateException(e);
}
}
Then I call it on run() method inside the MainActivity class like below:
public void run() {
if (i == 100) {
return;
}
SensorEvent event = null;
// events is the default topic for MQTT communication
String subtopic = "events";
// Your message you want to send
String message = "Hello World " + i++;
int acceleration = mAccelerometerActivity.onSensorChanged(SensorEvent event.values);
communicator.publishMessage(subtopic, message, acceleration);
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1));
}
};
But I still have this error in the below screenshot:
(';' or ) expected)
Also the third input I added is shown like never been used as you see in the screenshot below, is this has any effect?
Thank you.
I tried to read a json string loading from an URL, but I could not find complete code sample. Can any one provide or point me to a complete client code. I'm newer to BB development.
this is what I have done but still can't get it work please help me.
Thanks!
To read and parse data from an URL you need to implement two routines. First one of them will handle reading data from the specified URL over HTTP connection, and the second one will parse the data.
Check the following application HttpUrlReaderDemoApp, which will first read the data from specified URL and then parse the retrieved data.
URL used to retrieve data: http://codeincloud.tk/json_android_example.php
Sample data format: {"name":"Froyo", "version":"Android 2.2"}
Classes:
HttpUrlReaderDemoApp - UiApplication instance
HttpResponseListener - Interface used to notify other classes about HTTP request status
HttpUrlReader - Reads the data from given url
AppMainScreen - MainScreen instance
DataParser - Parse data
DataModel - Data definition
Screenshots:
Request for data
When data retrieved successfully
Parsed data
Implementation:
HttpUrlReaderDemoApp
public class HttpUrlReaderDemoApp extends UiApplication {
public static void main(String[] args) {
HttpUrlReaderDemoApp theApp = new HttpUrlReaderDemoApp();
theApp.enterEventDispatcher();
}
public HttpUrlReaderDemoApp() {
pushScreen(new AppMainScreen("HTTP Url Reader Demo Application"));
}
}
HttpResponseListener
public interface HttpResponseListener {
public void onHttpResponseFail(String message, String url);
public void onHttpResponseSuccess(byte bytes[], String url);
}
HttpUrlReader
public class HttpUrlReader implements Runnable {
private String url;
private HttpResponseListener listener;
public HttpUrlReader(String url, HttpResponseListener listener) {
this.url = url;
this.listener = listener;
}
private String getConncetionDependentUrlSuffix() {
// Not implemented
return "";
}
private void notifySuccess(byte bytes[], String url) {
if (listener != null) {
listener.onHttpResponseSuccess(bytes, url);
}
}
private void notifyFailure(String message, String url) {
if (listener != null) {
listener.onHttpResponseFail(message, url);
}
}
private boolean isValidUrl(String url) {
return (url != null && url.length() > 0);
}
public void run() {
if (!isValidUrl(url) || listener == null) {
String message = "Invalid parameters.";
message += !isValidUrl(url) ? " Invalid url." : "";
message += (listener == null) ? " Invalid HttpResponseListerner instance."
: "";
notifyFailure(message, url);
return;
}
// update URL depending on connection type
url += DeviceInfo.isSimulator() ? ";deviceside=true"
: getConncetionDependentUrlSuffix();
// Open the connection and retrieve the data
try {
HttpConnection httpConn = (HttpConnection) Connector.open(url);
int status = httpConn.getResponseCode();
if (status == HttpConnection.HTTP_OK) {
InputStream input = httpConn.openInputStream();
byte[] bytes = IOUtilities.streamToBytes(input);
input.close();
notifySuccess(bytes, url);
} else {
notifyFailure("Failed to retrieve data, HTTP response code: "
+ status, url);
return;
}
httpConn.close();
} catch (Exception e) {
notifyFailure("Failed to retrieve data, Exception: ", e.toString());
return;
}
}
}
AppMainScreen
public class AppMainScreen extends MainScreen implements HttpResponseListener {
private final String URL = "http://codeincloud.tk/json_android_example.php";
public AppMainScreen(String title) {
setTitle(title);
}
private MenuItem miReadData = new MenuItem("Read data", 0, 0) {
public void run() {
requestData();
}
};
protected void makeMenu(Menu menu, int instance) {
menu.add(miReadData);
super.makeMenu(menu, instance);
}
public void close() {
super.close();
}
public void showDialog(final String message) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(message);
}
});
}
private void requestData() {
Thread urlReader = new Thread(new HttpUrlReader(URL, this));
urlReader.start();
showDialog("Request for data from\n \"" + URL + "\"\n started.");
}
public void onHttpResponseFail(String message, String url) {
showDialog("Failure Mesage:\n" + message + "\n\nUrl:\n" + url);
}
public void onHttpResponseSuccess(byte bytes[], String url) {
showDialog("Data retrived from:\n" + url + "\n\nData:\n"
+ new String(bytes));
// now parse response
DataModel dataModel = DataParser.getData(bytes);
if (dataModel == null) {
showDialog("Failed to parse data: " + new String(bytes));
} else {
showDialog("Parsed Data:\nName: " + dataModel.getName()
+ "\nVersion: " + dataModel.getVersion());
}
}
}
DataParser
public class DataParser {
private static final String NAME = "name";
private static final String VERSION = "version";
public static DataModel getData(byte data[]) {
String rawData = new String(data);
DataModel dataModel = new DataModel();
try {
JSONObject jsonObj = new JSONObject(rawData);
if (jsonObj.has(NAME)) {
dataModel.setName(jsonObj.getString(NAME));
}
if (jsonObj.has(VERSION)) {
dataModel.setVersion(jsonObj.getString(VERSION));
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return dataModel;
}
}
DataModel
public class DataModel {
private String name;
private String version;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String model) {
this.version = model;
}
}
My XML is in following format
<users>
<user uid="1" dispname ="Yogesh C" statid="1" statmsg = "Busy">Yogesh Chaudhari</user>
<user uid="2" dispname ="Sameer S" statid="2" statmsg = "Available">Yogesh Chaudhari</user>
</users>
In my BlackBerry app, I want to change the value of a particualar attribute, such as statmsg for uid 2. Is it possible to do this using a SAX parser? My aim is to update the XML and restore it.
I used the following code for parsing my XML using SAX:
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileConnection;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
public class SaxParseUrl extends UiApplication {
public SaxParseUrl() {
pushScreen(new Pars());
}
public static void main(String[] args) {
SaxParseUrl app = new SaxParseUrl();
app.enterEventDispatcher();
}
}
class Pars extends MainScreen implements ContentHandler
{
boolean name;
Pars() {
try {
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(this);
FileConnection conn = (FileConnection)Connector.open("file:///store/home/user/employee.xml");
InputStream is = conn.openDataInputStream();
InputSource iss = new InputSource(is);
parser.parse(iss);
} catch (Exception e) {
debug("file:///store/home/user/SAXParser.txt","Exception in pars() :"+e);
}
}
public void startElement(String nsURI, String strippedName, String tagName,
Attributes attributes) throws SAXException {
try {
debug("file:///store/home/user/SAXParser.txt","startElement");
if (tagName.equalsIgnoreCase("user"))
{
debug("file:///store/home/user/SAXParser.txt","Inside startElement");
name = true;
String uid = attributes.getValue("uid");
String dispname = attributes.getValue("dispname");
String statid = attributes.getValue("statid");
String statmsg = attributes.getValue("statmsg");
attributes.
//LabelField lb = new LabelField(uid+"==>"+dispname+"==>"+statid+"==>"+statmsg);
LabelField lb = new LabelField("uid ==>"+uid+"\ndispname==>"+dispname+"\nstatid==>"+statid+"\nstatmsg==>"+statmsg);
add(lb);
}
} catch (Exception e) {
System.out.println(e);
}
}
public void characters(char[] ch, int start, int length) {
debug("file:///store/home/user/SAXParser.txt","characters");
if (name) {
try {
System.out.println("Title: " + new String(ch, start, length));
LabelField lb=new LabelField(""+ new String(ch, start, length));
HorizontalFieldManager sr=new HorizontalFieldManager();
sr.add(lb);
add(sr);
//v_cid.addElement(new String(ch, start, length));
//System.out.println("the elements of vector: " + v_cid);
// name = false;
//Enumeration e = v_cid.elements();
//System.out.println("The elements of vector: " + v_cid);
//while (e.hasMoreElements()) {
//System.out.println("The elements are: " + e.nextElement());
//}*/
} catch (Exception e) {
System.out.println(e);
}
}
}
public void endDocument() throws SAXException {
debug("file:///store/home/user/SAXParser.txt","endDocument");
}
public void endElement(String uri, String localName, String tagName)
throws SAXException {
debug("file:///store/home/user/SAXParser.txt","endElement");
}
public void endPrefixMapping(String prefix) throws SAXException {
debug("file:///store/home/user/SAXParser.txt","endPrefixMapping");
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
debug("file:///store/home/user/SAXParser.txt","ignorableWhitespace");
}
public void processingInstruction(String target, String data)
throws SAXException {
debug("file:///store/home/user/SAXParser.txt","processingInstruction");
}
public void setDocumentLocator(Locator locator) {
debug("file:///store/home/user/SAXParser.txt","setDocumentLocator");
}
public void skippedEntity(String name) throws SAXException {
}
public void startDocument() throws SAXException {
debug("file:///store/home/user/SAXParser.txt","startDocument");
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
debug("file:///store/home/user/SAXParser.txt","startPrefixMapping");
}
public static void debug(String strFileName,String strData)
{
FileConnection fc = null;
StringBuffer strbufData = null;
OutputStream ops = null;
try
{
fc = (FileConnection)Connector.open(strFileName,Connector. READ_WRITE);
//create the file if it doesnt exist
if(!fc.exists())
{
fc.create();
}
InputStream is = fc.openDataInputStream();
strbufData = new StringBuffer();
int intCh;
while((intCh = is.read())!= -1)
{
strbufData.append((char)intCh);
}
strbufData.append("\n\n"+strData);
String strFileContent = new String(strbufData.toString());
byte byteData[] = strFileContent.getBytes();
ops = fc.openOutputStream();
ops.write(byteData);
}
catch(Exception e)
{
Dialog.alert("Exception in writing logs :"+e);
}
finally
{
if(ops != null)
{
try
{
ops.close();
}catch(Exception e)
{
}
}
if(fc != null)
{
try
{
fc.close();
}catch(Exception e)
{
}
}
}
}
}
I have the oauth authorization with google working correctly and am getting data from the contacts api. Now, I want to programmatically get a gmail user's first name, last name and picture. Which google api can i use to get this data?
The contacts API perhaps works, but you have to request permission from the user to access all contacts. If I were a user, that would make me wary of granting the permission (because this essentially gives you permission to spam all my contacts...)
I found the response here to be useful, and only asks for "basic profile information":
Get user info via Google API
I have successfully used this approach, and can confirm it returns the following Json object:
{
"id": "..."
"email": "...",
"verified_email": true,
"name": "....",
"given_name": "...",
"family_name": "...",
"link": "...",
"picture": "...",
"gender": "male",
"locale": "en"
}
Use this code to get firstName and lastName of a google user:
final HttpTransport transport = new NetHttpTransport();
final JsonFactory jsonFactory = new JacksonFactory();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(Arrays.asList(clientId))
.setIssuer("https://accounts.google.com")
.build();
GoogleIdToken idToken = null;
try {
idToken = verifier.verify(googleAuthenticationPostResponse.getId_token());
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
GoogleIdToken.Payload payload = null;
if (idToken != null) {
payload = idToken.getPayload();
}
String firstName = payload.get("given_name").toString();
String lastName = payload.get("family_name").toString();
If you're using the google javascript API, you can use the new "auth2" API after authenticating to get the user's profile, containing:
name
email
image URL
https://developers.google.com/identity/sign-in/web/reference#googleusergetbasicprofile
For the picture, you can use the Google contacts Data API too: see http://code.google.com/intl/fr/apis/contacts/docs/3.0/developers_guide_protocol.html#retrieving_photo
The simplest way to get this information would be from the Google + API. Specifically the
https://developers.google.com/+/api/latest/people/get
When using the api use the following HTTP GET:
GET https://www.googleapis.com/plus/v1/people/me
This will return all of the above information requested from the user.
I found the answer while looking around in the contacts API forum. When you get the result-feed, just do the following in Java-
String Name = resultFeed.getAuthors().get(0).getName();
String emailId = resultFeed.getId();
I am still looking for a way to get the user profile picture.
Use this Code for Access Google Gmail Login Credential oAuth2 :
Class Name : OAuthHelper
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map.Entry;
import java.util.SortedSet;
import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.commonshttp.HttpRequestAdapter;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import oauth.signpost.http.HttpParameters;
import oauth.signpost.signature.HmacSha1MessageSigner;
import oauth.signpost.signature.OAuthMessageSigner;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.util.Log;
public class OAuthHelper {
private static final String TAG = "OAuthHelper";
private OAuthConsumer mConsumer;
private OAuthProvider mProvider;
private String mCallbackUrl;
public OAuthHelper(String consumerKey, String consumerSecret, String scope, String callbackUrl) throws UnsupportedEncodingException {
mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
mProvider = new CommonsHttpOAuthProvider("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + URLEncoder.encode(scope, "utf-8"), "https://www.google.com/accounts/OAuthGetAccessToken", "https://www.google.com/accounts/OAuthAuthorizeToken?hd=default");
mProvider.setOAuth10a(true);
mCallbackUrl = (callbackUrl == null ? OAuth.OUT_OF_BAND : callbackUrl);
}
public String getRequestToken() throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {
String authUrl = mProvider.retrieveRequestToken(mConsumer, mCallbackUrl);
System.out.println("Gautam AUTH URL : " + authUrl);
return authUrl;
}
public String[] getAccessToken(String verifier) throws OAuthMessageSignerException, OAuthNotAuthorizedException, OAuthExpectationFailedException, OAuthCommunicationException {
mProvider.retrieveAccessToken(mConsumer, verifier);
return new String[] { mConsumer.getToken(), mConsumer.getTokenSecret() };
}
public String[] getToken() {
return new String[] { mConsumer.getToken(), mConsumer.getTokenSecret() };
}
public void setToken(String token, String secret) {
mConsumer.setTokenWithSecret(token, secret);
}
public String getUrlContent(String url) throws OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException, IOException {
HttpGet request = new HttpGet(url);
// sign the request
mConsumer.sign(request);
// send the request
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
// get content
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
sb.append(line + NL);
in.close();
System.out.println("gautam INFO : " + sb.toString());
return sb.toString();
}
public String getUserProfile(String t0, String t1, String url) {
try {
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(t0, t1);
HttpGet request = new HttpGet(url);
// sign the request
consumer.sign(request);
// send the request
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
//String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
sb.append(line );
in.close();
System.out.println("Gautam Profile : " + sb.toString());
return sb.toString();
} catch (Exception e) {
System.out.println("Error in Geting profile Info : " + e);
return "";
}
}
public String buildXOAuth(String email) {
String url = String.format("https://mail.google.com/mail/b/%s/smtp/", email);
HttpRequestAdapter request = new HttpRequestAdapter(new HttpGet(url));
// Sign the request, the consumer will add any missing parameters
try {
mConsumer.sign(request);
} catch (OAuthMessageSignerException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
} catch (OAuthExpectationFailedException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
} catch (OAuthCommunicationException e) {
Log.e(TAG, "failed to sign xoauth http request " + e);
return null;
}
HttpParameters params = mConsumer.getRequestParameters();
// Since signpost doesn't put the signature into params,
// we've got to create it again.
OAuthMessageSigner signer = new HmacSha1MessageSigner();
signer.setConsumerSecret(mConsumer.getConsumerSecret());
signer.setTokenSecret(mConsumer.getTokenSecret());
String signature;
try {
signature = signer.sign(request, params);
} catch (OAuthMessageSignerException e) {
Log.e(TAG, "invalid oauth request or parameters " + e);
return null;
}
params.put(OAuth.OAUTH_SIGNATURE, OAuth.percentEncode(signature));
StringBuilder sb = new StringBuilder();
sb.append("GET ");
sb.append(url);
sb.append(" ");
int i = 0;
for (Entry<String, SortedSet<String>> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue().first();
int size = entry.getValue().size();
if (size != 1)
Log.d(TAG, "warning: " + key + " has " + size + " values");
if (i++ != 0)
sb.append(",");
sb.append(key);
sb.append("=\"");
sb.append(value);
sb.append("\"");
}
Log.d(TAG, "xoauth encoding " + sb);
Base64 base64 = new Base64();
try {
byte[] buf = base64.encode(sb.toString().getBytes("utf-8"));
return new String(buf, "utf-8");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "invalid string " + sb);
}
return null;
}
}
//===================================
Create : WebViewActivity.class
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewActivity extends Activity {
//WebView webview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
WebView webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
setContentView(webview);
// Load the page
Intent intent = getIntent();
if (intent.getData() != null) {
webview.loadUrl(intent.getDataString());
}
webview.setWebChromeClient(new WebChromeClient() {
// Show loading progress in activity's title bar.
#Override
public void onProgressChanged(WebView view, int progress) {
setProgress(progress * 100);
}
});
webview.setWebViewClient(new WebViewClient() {
// When start to load page, show url in activity's title bar
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
setTitle(url);
if (url.startsWith("my-activity")) {
Intent result = new Intent();
System.out.println("Gautam my-activity : " + url);
result.putExtra("myurl", url);
setResult(RESULT_OK, result);
finish();
}
}
#Override
public void onPageFinished(WebView view, String url) {
System.out.println("Gautam Page Finish...");
CookieSyncManager.getInstance().sync();
// Get the cookie from cookie jar.
String cookie = CookieManager.getInstance().getCookie(url);
System.out.println("Gautam Cookie : " + cookie);
if (cookie == null) {
return;
}
// Cookie is a string like NAME=VALUE [; NAME=VALUE]
String[] pairs = cookie.split(";");
for (int i = 0; i < pairs.length; ++i) {
String[] parts = pairs[i].split("=", 2);
// If token is found, return it to the calling activity.
System.out.println("Gautam=> "+ parts[0] + " = " + parts[1]);
if (parts.length == 2 && parts[0].equalsIgnoreCase("oauth_token")) {
Intent result = new Intent();
System.out.println("Gautam AUTH : " + parts[1]);
result.putExtra("token", parts[1]);
setResult(RESULT_OK, result);
finish();
}
}
}
});
}
}
//=========================
Call From : MainActivity.class
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.http.HttpResponse;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
Button btnLogin;
OAuthHelper MyOuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLogin = (Button)findViewById(R.id.btnLogin);
btnLogin.setOnClickListener(this);
}
#Override
protected void onResume() {
/*System.out.println("On Resume call ");
try {
String[] token = getVerifier();
if (token != null){
String accessToken[] = MyOuthHelper.getAccessToken(token[1]);
}
} catch (Exception e) {
System.out.println("gautam error on Resume : " + e);
}*/
super.onResume();
}
private String[] getVerifier(String url) {
// extract the token if it exists
Uri uri = Uri.parse(url);
if (uri == null) {
return null;
}
String token = uri.getQueryParameter("oauth_token");
String verifier = uri.getQueryParameter("oauth_verifier");
return new String[] { token, verifier };
}
#Override
public void onClick(View v) {
try {
MyOuthHelper = new OAuthHelper("YOUR CLIENT ID", "YOUR SECRET KEY", "https://www.googleapis.com/auth/userinfo.profile", "my-activity://localhost");
} catch (Exception e) {
System.out.println("gautam errorin Class call : " + e);
}
try {
String uri = MyOuthHelper.getRequestToken();
Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
intent.setData(Uri.parse(uri));
startActivityForResult(intent, 0);
/* startActivity(new Intent("android.intent.action.VIEW",
Uri.parse(uri)));*/
} catch (Exception e) {
System.out.println("Gautm Error in getRequestTokan : " + e);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 0:
if (resultCode != RESULT_OK || data == null) {
return;
}
// Get the token.
String url = data.getStringExtra("myurl");
try {
String[] token = getVerifier(url);
if (token != null){
String accessToken[] = MyOuthHelper.getAccessToken(token[1]);
System.out.println("Gautam Final [0] : " + accessToken[0] + " , [1] : " + accessToken[1]);
//https://www.googleapis.com/oauth2/v1/userinfo?alt=json
// String myProfile = MyOuthHelper.getUserProfile(accessToken[0], accessToken[1], "https://www.googleapis.com/oauth2/v1/userinfo?alt=json");
String myProfile = MyOuthHelper.getUrlContent("https://www.googleapis.com/oauth2/v1/userinfo?alt=json");
}
} catch (Exception e) {
System.out.println("gautam error on Resume : " + e);
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
//=================================
And Finally Your Profile Information coming, Just Look in your Logcat message print.
Note : Not Forgot to put Internet Permission in Manifest File
And Your App Register in Google Console for Client ID and Secret Key
For App Registration Please Looking this Step : App Registration Step