I want to create a spreadsheet programmatically in android studio. how can I do that?
I used OAuth for signing in the user and now wants to create the spreadsheet in his drive folder.
I found the below code but don't know how to use it...
Spreadsheet spreadsheet = new Spreadsheet()
.setProperties(new SpreadsheetProperties()
.setTitle(title));
spreadsheet = service.spreadsheets().create(spreadsheet)
.setFields("spreadsheetId")
.execute();
System.out.println("Spreadsheet ID: " + spreadsheet.getSpreadsheetId());
For creating a Google Sheet in a programmatic way you should try to use Sheet API. More specifcally you need to use the create method.
If you are using the Google libraries for Java you could just try to follow the example in the create endpoint:
/*
* BEFORE RUNNING:
* ---------------
* 1. If not already done, enable the Google Sheets API
* and check the quota for your project at
* https://console.developers.google.com/apis/api/sheets
* 2. Install the Java client library on Maven or Gradle. Check installation
* instructions at https://github.com/google/google-api-java-client.
* On other build systems, you can add the jar files to your project from
* https://developers.google.com/resources/api-libraries/download/sheets/v4/java
*/
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.Spreadsheet;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class SheetsExample {
public static void main(String args[]) throws IOException, GeneralSecurityException {
// TODO: Assign values to desired fields of `requestBody`:
Spreadsheet requestBody = new Spreadsheet();
Sheets sheetsService = createSheetsService();
Sheets.Spreadsheets.Create request = sheetsService.spreadsheets().create(requestBody);
Spreadsheet response = request.execute();
// TODO: Change code below to process the `response` object:
System.out.println(response);
}
public static Sheets createSheetsService() throws IOException, GeneralSecurityException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
// TODO: Change placeholder below to generate authentication credentials. See
// https://developers.google.com/sheets/quickstart/java#step_3_set_up_the_sample
//
// Authorize using one of the following scopes:
// "https://www.googleapis.com/auth/drive"
// "https://www.googleapis.com/auth/drive.file"
// "https://www.googleapis.com/auth/spreadsheets"
GoogleCredential credential = null;
return new Sheets.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("Google-SheetsSample/0.1")
.build();
}
}
This example is not handling credentials and you will need to change this in order to work
In case you need more information in the libraries read through the Java Quickstart to work from there, also look at the java create method. And of course you can just do an HTTP request if you have already managed all the OAuth part.
Related
I need some help guys!! I am a self-taught, newbie in encryption, and after reading, testing, and error for more than two weeks on how to solve this, and finding very little crowd knowledge and almost no documentation from Google.
I am trying to read the integrity verdict, that I have managed to get it IntegrityTokenRequest doing
String nonce = Base64.encodeToString("this_is_my_nonce".getBytes(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
IntegrityManager myIntegrityManager = IntegrityManagerFactory
.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> myIntegrityTokenResponse = myIntegrityManager
.requestIntegrityToken(IntegrityTokenRequest
.builder()
.setNonce(nonce)
.build());
myIntegrityTokenResponse.addOnSuccessListener(new OnSuccessListener<IntegrityTokenResponse>() {
#Override
public void onSuccess(IntegrityTokenResponse myIntegrityTokenResponse) {
String token = myIntegrityTokenResponse.token();
// so here I have my Integrity token.
// now how do I read it??
}
}
As per the documentation, it's all set up in the Play Console, and created the Google Cloud project accordingly. Now here comes the big hole in the documentation:
a) The JWT has 4 dots that divide the JWT into 5 sections, not in 3 sections as described here https://jwt.io/
b) Developer.Android.com recommends to Decrypt and Verify on Google Servers
I have no idea on how or were to execute this command... :-(
c) if I choose to decrypt and verify the returned token it's more complicated as I don't have my own secure server environment, only my App and the Google Play Console.
d) I found in the Google Clound Platform OAuth 2.0 Client IDs "Android client for com.company.project" JSON file that I have downloaded, but no clue (again) on how to use it in my App for getting the veredict from the Integrity Token.
{"installed":
{"client_id":"123456789012-abcdefghijklmnopqrstuvwxyza0g2ahk.apps.googleusercontent.com",
"project_id":"myproject-360d3",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":https://www.googleapis.com/oauth2/v1/certs
}
}
I'm sure I am missing a lot, please help
Using a cloud server to decode and verify the token is better.
For example, if you going with Java service then the below code will send the integrity token to the google server hence you can verify the response.
Enable PlayIntegrity API in Google Cloud Platform against the app and download the JSON file and configure in the code.
Similarly, you should enable PlayIntegrity API in Google PlayConsole against the app
Add Google Play Integrity Client Library to your project
Maven Dependency
<project>
<dependencies>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-playintegrity</artifactId>
<version>v1-rev20220211-1.32.1</version>
</dependency>
</dependencies>
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.apis:google-api-services-playintegrity:v1-rev20220211-1.32.1'
}
Token decode
DecodeIntegrityTokenRequest requestObj = new DecodeIntegrityTokenRequest();
requestObj.setIntegrityToken(request.getJws());
//Configure downloaded Json file
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("<Path of JSON file>\\file.json"));
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
GoogleClientRequestInitializer initialiser = new PlayIntegrityRequestInitializer();
Builder playIntegrity = new PlayIntegrity.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer).setApplicationName("testapp")
.setGoogleClientRequestInitializer(initialiser);
PlayIntegrity play = playIntegrity.build();
DecodeIntegrityTokenResponse response = play.v1().decodeIntegrityToken("com.test.android.integritysample", requestObj).execute();
Then the response will be as follows
{
"tokenPayloadExternal": {
"accountDetails": {
"appLicensingVerdict": "LICENSED"
},
"appIntegrity": {
"appRecognitionVerdict": "PLAY_RECOGNIZED",
"certificateSha256Digest": ["pnpa8e8eCArtvmaf49bJE1f5iG5-XLSU6w1U9ZvI96g"],
"packageName": "com.test.android.integritysample",
"versionCode": "4"
},
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"]
},
"requestDetails": {
"nonce": "SafetyNetSample1654058651834",
"requestPackageName": "com.test.android.integritysample",
"timestampMillis": "1654058657132"
}
}
}
Check for License
String licensingVerdict = response.getTokenPayloadExternal().getAccountDetails().getAppLicensingVerdict();
if(!licensingVerdict.equalsIgnoreCase("LICENSED")) {
throw new Exception("Licence is not valid.");
}
Verify App Integrity
public void checkAppIntegrity(DecodeIntegrityTokenResponse response, String appId) throws Exception {
AppIntegrity appIntegrity = response.getTokenPayloadExternal().getAppIntegrity();
if(!appIntegrity.getAppRecognitionVerdict().equalsIgnoreCase("PLAY_RECOGNIZED")) {
throw new Exception("The certificate or package name does not match Google Play records.");
}
if(!appIntegrity.getPackageName().equalsIgnoreCase(appId)) {
throw new Exception("App package name mismatch.");
}
if(appIntegrity.getCertificateSha256Digest()!= null) {
//If the app is deployed in Google PlayStore then Download the App signing key certificate from Google Play Console (If you are using managed signing key).
//otherwise download Upload key certificate and then find checksum of the certificate.
Certificate cert = getCertificate("<Path to Signing certificate>\deployment_cert.der");
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] der = cert.getEncoded();
md.update(der);
byte[] sha256 = md.digest();
//String checksum = Base64.getEncoder().encodeToString(sha256);
String checksum = Base64.getUrlEncoder().encodeToString(sha256);
/** Sometimes checksum value ends with '=' character, you can avoid this character before perform the match **/
checksum = checksum.replaceAll("=","");
if(!appIntegrity.getCertificateSha256Digest().get(0).contains(checksum)) {
throw new Exception("App certificate mismatch.");
}
}
}
public static Certificate getCertificate(String certificatePath)
throws Exception {
CertificateFactory certificateFactory = CertificateFactory
.getInstance("X509");
FileInputStream in = new FileInputStream(certificatePath);
Certificate certificate = certificateFactory
.generateCertificate(in);
in.close();
return certificate;
}
Verify Device integrity
//Check Device Integrity
public void deviceIntegrity(DecodeIntegrityTokenResponse response) {
DeviceIntegrity deviceIntegrity = response.getTokenPayloadExternal().getDeviceIntegrity();
if(!deviceIntegrity.getDeviceRecognitionVerdict().contains("MEETS_DEVICE_INTEGRITY")) {
throw new Exception("Does not meet Device Integrity.");
}
}
Similary you can verify the Nonce and App Package name with previously stored data in server
Thanks a lot #John_S for your answer, I'll mark it as the final answer, anyway I post here all the missing parts for future developers so they can shortcut my almost one month sucked in this issue, as there is no complete documentation nor java examples (at the time of writing this) for the Google PlayIntegrity API.
First, you need to set our project in the Google Cloud, and Google Play as stated by #John_S, but the missing part is that you need to set a Credential as "Service Account" and then "Add Key" as described java.io.IOException: Error reading credentials from stream, 'type' field not specified and this https://developers.google.com/workspace/guides/create-credentials#android; then, you can download the .json file with your Credentials. The .json file described in my question is invalid as it must have a structure like this:
{ "type": "service_account",
"project_id": "your-project",
"private_key_id": "your-key-id",
"private_key": "your-private-key",
"client_email": "your-email#appspot.gserviceaccount.com",
"client_id": "your-client-id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/your-email%40appspot.gserviceaccount.com"
}
Second, once you have your valid .json file downloaded, store it in "src/main/resources/credentials.json" (create the new folder if needed, not into "res" folder), as stated here Where must the client_secrets.json file go in Android Studio project folder tree?
Third, to complete all the missing parts of the build.gradle you must include:
dependencies {
implementation 'com.google.android.play:integrity:1.0.1'
implementation 'com.google.apis:google-api-services-playintegrity:v1-rev20220211-1.32.1'
implementation 'com.google.api-client:google-api-client-jackson2:1.20.0'
implementation 'com.google.auth:google-auth-library-credentials:1.7.0'
implementation 'com.google.auth:google-auth-library-oauth2-http:1.7.0'
}
And import them to your project
import com.google.android.gms.tasks.Task;
import com.google.android.play.core.integrity.IntegrityManager;
import com.google.android.play.core.integrity.IntegrityManagerFactory;
import com.google.android.play.core.integrity.IntegrityTokenRequest;
import com.google.android.play.core.integrity.IntegrityTokenResponse;
import com.google.api.services.playintegrity.v1.PlayIntegrity;
import com.google.api.services.playintegrity.v1.PlayIntegrityRequestInitializer;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.services.playintegrity.v1.model.DecodeIntegrityTokenRequest;
import com.google.api.services.playintegrity.v1.model.DecodeIntegrityTokenResponse;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
Then, the complete code for requesting the "Integrity Token" and decode it will be:
// create the NONCE Base64-encoded, URL-safe, and non-wrapped String
String mynonce = Base64.encodeToString("this_is_my_nonce".getBytes(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
// Create an instance of a manager.
IntegrityManager myIntegrityManager = IntegrityManagerFactory.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> myIntegrityTokenResponse = myIntegrityManager
.requestIntegrityToken(IntegrityTokenRequest
.builder()
.setNonce(mynonce)
// .setCloudProjectNumber(cloudProjNumber) // necessary only if sold outside Google Play
.build());
// get the time to check against the decoded integrity token time
timeRequest = Calendar.getInstance().getTimeInMillis();
myIntegrityTokenResponse.addOnSuccessListener(new OnSuccessListener<IntegrityTokenResponse>() {
#Override
public void onSuccess(IntegrityTokenResponse myIntegrityTokenResponse) {
try {
String token = myIntegrityTokenResponse.token();
DecodeIntegrityTokenRequest requestObj = new DecodeIntegrityTokenRequest();
requestObj.setIntegrityToken(token);
//Configure your credentials from the downloaded Json file from the resource
GoogleCredentials credentials = GoogleCredentials.fromStream(Objects.requireNonNull(getClass().getClassLoader()).getResourceAsStream("credentials.json"));
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
GoogleClientRequestInitializer initializer = new PlayIntegrityRequestInitializer();
PlayIntegrity.Builder playIntegrity = new PlayIntegrity.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer).setApplicationName("your-project")
.setGoogleClientRequestInitializer(initializer);
PlayIntegrity play = playIntegrity.build();
// the DecodeIntegrityToken must be run on a parallel thread
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
DecodeIntegrityTokenResponse response = play.v1().decodeIntegrityToken("com.project.name", requestObj).execute();
String licensingVerdict = response.getTokenPayloadExternal().getAccountDetails().getAppLicensingVerdict();
if (licensingVerdict.equalsIgnoreCase("LICENSED")) {
// Looks good! LICENSED app
} else {
// LICENSE NOT OK
}
} catch (Exception e) {
// LICENSE error
}
}
});
// execute the parallel thread
thread.start();
} catch (Error | IOException e) {
// LICENSE error
} catch (Exception e) {
// LICENSE error
}
}
});
Hope this helps.
I'm new to the Google App Engine, and I'm trying to make my first engine and connect it to my Android app. I have walked through this tutorial in order to learn about it:
https://cloud.google.com/endpoints/docs/frameworks/legacy/v1/java/helloendpoints-android-studio
I got it to work fine. I can access my app engine from my android app, and get the wanted response. The problem is, I want to restrict the endpoints of my API to my app's users only.
This is my API method (from the tutorial), and as for now, everyone can access my api's explorer and execute methods in it, as long as they are logged in to any Google account.
I want the users to be able to execute this method from my app only.
This is my app engine java file:
package com.example.Barda.myapplication.backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.UnauthorizedException;
import com.google.appengine.api.users.User;
import javax.inject.Named;
/**
* An endpoint class we are exposing
*/
#Api(
name = "myApi",
version = "v1",
clientIds = {Constants.ANDROID_CLIENT_ID},
audiences="firebase-wiki-race.appspot.com",
namespace = #ApiNamespace(
ownerDomain = "backend.myapplication.Barda.example.com",
ownerName = "backend.myapplication.Barda.example.com",
packagePath = ""
)
)
public class MyEndpoint {
/**
* A simple endpoint method that takes a name and says Hi back
*/
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String name) throws UnauthorizedException {
// if (user == null) throw new UnauthorizedException("User is Not Valid");
MyBean response = new MyBean();
response.setData("Hi, " + name);
return response;
}
}
This is constants class:
package com.example.Barda.myapplication.backend;
/**
* Contains the client IDs and scopes for allowed clients consuming your API.
*/
public class Constants {
public static final String ANDROID_CLIENT_ID = "*********************.apps.googleusercontent.com";
}
I have generated using my app's SH-1 and package name the ANDROID_CLIENT_ID.
I have searched online a lot, and read blogs and threads, but I couldn't make it work. Is this a possible thing to do? What am I doing wrong?
You'll want to follow the documentation's guide on adding authorization to the API backend. In this process you define a list of clients that are authorized to use your Endpoint.
Once that's done you can follow the guide on making authenticated calls from Android.
I followed the "Android Quickstart" below.
https://developers.google.com/sheets/api/quickstart/android
Works great.
But the sample hard-codes a spreadsheetId to an existing spreadsheet.
String spreadsheetId = "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms";
I need to be able to find an existing spreadsheet, by name, and store the id (for later use).
I'd like to do something like this:
private com.google.api.services.sheets.v4.Sheets sheetsService = null;
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
sheetsService = new com.google.api.services.sheets.v4.Sheets.Builder(
transport, jsonFactory, credential)
.setApplicationName("My Application Name")
.build();
String spreadsheetId = null;
List<Spreadsheet> allSpreadsheets = sheetsService.spreadsheets().getAListOfAllSpreadsheets;
for (Spreadsheet spreadsheet : allSpreadsheets) {
if (spreadsheet.getName().equals("My Sheet")){
// found!
spreadsheetId = spreadsheet.getId();
}
}
Much thanks in advance!
It looks like this cannot be done with Sheets API v4.
However...it does look like it can be done with the compatible Google Drive API v3.
Note: the best part about this solution was that I could use the same method of authentication and credential gathering for both APIs. E.g., once I had the code for getting the credentials, I could use it for both API's interchangeably and consecutively.
Here's what I did:
Added this to my build.gradle (shown below my Sheets API declaration)
compile('com.google.apis:google-api-services-sheets:v4-rev468-1.22.0') {
exclude group: 'org.apache.httpcomponents'
}
compile('com.google.apis:google-api-services-drive:v3-rev69-1.22.0') {
exclude group: 'org.apache.httpcomponents'
}
I was already using the EasyPermissions method for getting account and credentials. Great example here.
Then...
import com.google.api.services.drive.Drive;
import com.google.api.services.sheets.v4.Sheets;
...
private static final String[] SCOPES = { SheetsScopes.SPREADSHEETS, DriveScopes.DRIVE_METADATA_READONLY };
...
credentials = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES));
...
protected Drive driveService = new Drive.Builder(transport, jsonFactory, credential)
.setApplicationName("My Application Name")
.build();
protected Sheets sheetsService = new Sheets.Builder(transport, jsonFactory, credential)
.setApplicationName("My Application Name")
.build();
... async:
Drive.Files.List request = driveService.files().list()
.setPageSize(10)
// Available Query parameters here:
//https://developers.google.com/drive/v3/web/search-parameters
.setQ("mimeType = 'application/vnd.google-apps.spreadsheet' and name contains 'smith' and trashed = false")
.setFields("nextPageToken, files(id, name)");
FileList result = request.execute();
List<File> files = result.getFiles();
String spreadsheetId = null;
if (files != null) {
for (File file : files) {
// More code here to discriminate best result, if you want
spreadsheetId = file.getId();
}
}
Then you can directly use the id for the Sheets API:
ValueRange response = sheetsService.spreadsheets().values().get(spreadsheetId, "A1:B2").execute();
List<List<Object>> values = response.getValues();
It looks to me like you're confusing Spreadsheet and Sheet objects:
a Spreadsheet is a file with an Id, accessible by a URL such as https://docs.google.com/spreadsheets/d/yourSpreadsheetId; it is a document stored in a Google Drive folder (like an Excel workbook).
a Sheet is a tab in a Spreadsheet, with cells, like a page in your workbook. It has no Id and no direct URL. Well actually the API v4 reference indicate that Sheets also have Ids, but confusingly enough these are just reference numbers that you cannot even access in Google Apps Script, and wouldn't help you in your problem.
So you cannot access a range directly in a Spreadsheet, nor can you find a Sheet by Id.
Similarly enough to your answer, here is what I would suggest:
_ Browse through your Drive files (filter by mimeType == "application/vnd.google-apps.spreadsheet")
__For each Spreadsheet file, browse its Sheets (spreadsheet.sheets[])
___For each Sheet in the current Spreadsheet, check whether it's the one by looking at its name (sheet.title)
Once you found the right sheet, you can get its containing Spreadsheet's Id (spreadsheet.spreadsheetId).
One more thing: at the bottom of your answer, you wrote
ValueRange response = sheetsService.spreadsheets().values().get(spreadsheetId, "A1:B2").execute();
You wouldn't be able to access a cell range from a spreadsheet without first specifying the Sheet containing the range: so instead of "A1:B2", you would need "mySheetTitle!A1:B2".
I hope this is clearing up the confusion :)
Is there any lightweight library for Android that acts like JAXB on the desktop?
Give an XML schema, create code to parse, validate, manipulate and then again write it.
The files already exist and since it's a finance application nothing that isn't modified must be touched. Including whitespace, ordering and character encoding.
(I'm doing this for years with JAXB and it works fine but I can't port that code to Android due to the lack of JAXB and it's footprint.)
You can try Simple Framework or Castor.
The following worked for me for validation:
Create a validation utility.
Get both the xml and xsd into file on the android OS and use the validation utility against it.
Use Xerces-For-Android to do the validation.
Android does support some packages which we can use, I created my xml validation utility based on: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html
My initial sandbox testing was pretty smooth with java, then I tried to port it over to Dalvik and found that my code did not work. Some things just aren't supported the same with Dalvik, so I made some modifications.
I found a reference to xerces for android, so I modified my sandbox test of (the following doesn't work with android, the example after this does):
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
/**
* A Utility to help with xml communication validation.
*/
public class XmlUtil {
/**
* Validation method.
* Base code/example from: http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/package-summary.html
*
* #param xmlFilePath The xml file we are trying to validate.
* #param xmlSchemaFilePath The schema file we are using for the validation. This method assumes the schema file is valid.
* #return True if valid, false if not valid or bad parse.
*/
public static boolean validate(String xmlFilePath, String xmlSchemaFilePath) {
// parse an XML document into a DOM tree
DocumentBuilder parser = null;
Document document;
// Try the validation, we assume that if there are any issues with the validation
// process that the input is invalid.
try {
// validate the DOM tree
parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
document = parser.parse(new File(xmlFilePath));
// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(new File(xmlSchemaFilePath));
Schema schema = factory.newSchema(schemaFile);
// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();
validator.validate(new DOMSource(document));
} catch (Exception e) {
// Catches: SAXException, ParserConfigurationException, and IOException.
return false;
}
return true;
}
}
The above code had to be modified some to work with xerces for android (http://gc.codehum.com/p/xerces-for-android/). You need SVN to get the project, the following are some crib notes:
download xerces-for-android
download silk svn (for windows users) from http://www.sliksvn.com/en/download
install silk svn (I did complete install)
Once the install is complete, you should have svn in your system path.
Test by typing "svn" from the command line.
I went to my desktop then downloaded the xerces project by:
svn checkout http://xerces-for-android.googlecode.com/svn/trunk/ xerces-for-android-read-only
You should then have a new folder on your desktop called xerces-for-android-read-only
With the above jar (Eventually I'll make it into a jar, just copied it directly into my source for quick testing. If you wish to do the same, you can making the jar quickly with Ant (http://ant.apache.org/manual/using.html)), I was able to get the following to work for my xml validation:
import java.io.File;
import java.io.IOException;
import mf.javax.xml.transform.Source;
import mf.javax.xml.transform.stream.StreamSource;
import mf.javax.xml.validation.Schema;
import mf.javax.xml.validation.SchemaFactory;
import mf.javax.xml.validation.Validator;
import mf.org.apache.xerces.jaxp.validation.XMLSchemaFactory;
import org.xml.sax.SAXException;
/**
* A Utility to help with xml communication validation.
*/public class XmlUtil {
/**
* Validation method.
*
* #param xmlFilePath The xml file we are trying to validate.
* #param xmlSchemaFilePath The schema file we are using for the validation. This method assumes the schema file is valid.
* #return True if valid, false if not valid or bad parse or exception/error during parse.
*/
public static boolean validate(String xmlFilePath, String xmlSchemaFilePath) {
// Try the validation, we assume that if there are any issues with the validation
// process that the input is invalid.
try {
SchemaFactory factory = new XMLSchemaFactory();
Source schemaFile = new StreamSource(new File(xmlSchemaFilePath));
Source xmlSource = new StreamSource(new File(xmlFilePath));
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
} catch (SAXException e) {
return false;
} catch (IOException e) {
return false;
} catch (Exception e) {
// Catches everything beyond: SAXException, and IOException.
e.printStackTrace();
return false;
} catch (Error e) {
// Needed this for debugging when I was having issues with my 1st set of code.
e.printStackTrace();
return false;
}
return true;
}
}
Some Side Notes:
For creating the files, I made a simple file utility to write string to files:
public static void createFileFromString(String fileText, String fileName) {
try {
File file = new File(fileName);
BufferedWriter output = new BufferedWriter(new FileWriter(file));
output.write(fileText);
output.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
I also needed to write to an area that I had access to, so I made use of:
String path = this.getActivity().getPackageManager().getPackageInfo(getPackageName(), 0).applicationInfo.dataDir;
A little hackish, it works. I'm sure there is a more succinct way of doing this, however I figured I'd share my success, as there weren't any good examples that I found.
I d like to upload a picture to a host like: http://imagerz.com/ .
Any sample for this? I can do a simple POST request, but how I can add the image content to my POST request?
Here is a tutorial that tells you how to send a file via FTP to a server. File upload and download using Java
It shouldn't be very hard to "port" that code into android. (You may have to change some of the classes/methods as some of them may not be implemented in Android's lightweight VM).
There are also other image hosting services that should have an api that you could follow.
EDIT:
As you stated, you wanted to do this with a post request.
I found this great tutorial with the following code:
package com.commonsbook.chap9;
import java.io.File;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.MultipartPostMethod;
public class HttpMultiPartFileUpload {
private static String url =
"http://localhost:8080/HttpServerSideApp/ProcessFileUpload.jsp";
public static void main(String[] args) throws IOException {
HttpClient client = new HttpClient();
MultipartPostMethod mPost = new MultipartPostMethod(url);
client.setConnectionTimeout(8000);
// Send any XML file as the body of the POST request
File f1 = new File("students.xml");
File f2 = new File("academy.xml");
File f3 = new File("academyRules.xml");
System.out.println("File1 Length = " + f1.length());
System.out.println("File2 Length = " + f2.length());
System.out.println("File3 Length = " + f3.length());
mPost.addParameter(f1.getName(), f1);
mPost.addParameter(f2.getName(), f2);
mPost.addParameter(f3.getName(), f3);
int statusCode1 = client.executeMethod(mPost);
System.out.println("statusLine>>>" + mPost.getStatusLine());
mPost.releaseConnection();
}
}
Source: http://www.theserverside.com/news/1365153/HttpClient-and-FileUpload
The same issues about porting this code to android as I stated above apply.