I am using google cloud storage to store images on android..I created project in google developers console and gave all id's from that project.
private static final String PROJECT_ID_PROPERTY = "xxxxxxxxxxxxxx"; //project ID
private static final String APPLICATION_NAME_PROPERTY = "refined"; //application name, can be any
private static final String ACCOUNT_ID_PROPERTY = "xxxxxxxxxxxxxxx-n5kqcd842faki0se7s82vpcf9l1rbvui#developer.gserviceaccount.com"; //user account email
Downloaded P12 file and accessing from the code for setting p12 key.
When I tried on 2 days back , images got uploaded correctly and I could see them in the browser..But when I try today the same code, it is giving forbidded issue.
{"code":403,"errors": [{"domain":"global","message":"Forbidden","reason":"forbidden"}],"message":"Forbidden"}
What could be the reason?
I could solve the issue...Issue was with permissions...
I gave write permissions on the bucket for the client ID, then it is working now.
Thanks for all
Related
I want to access a hsqldb database using android, but i get this error everytime java.sql.SQLException: Database lock acquisition failure: lockFile: org.hsqldb.persist.LockFile#dc61f9b4[file =/home/user/db/jade.lck,
this is my connexion class:
private static final String BDD_DRIVER = "org.hsqldb.jdbcDriver";
private static final String BDD_URI = "jdbc:hsqldb:file:home/user/db/jade;shutdown=true";
private static final String BDD_LOGIN = "sa";
private static final String BDD_PASS = "";
and this is how i get the connection:
Class.forName(BDD_DRIVER).newInstance();
connexion = DriverManager.getConnection(BDD_URI, BDD_LOGIN, BDD_PASS);
thank you for helping me.
When you get the error that you reported, it means the hsqldb.jar is present and an attempt was made to connect to the database. You must report the full error because after the file name, it includes the reason why there was a failure.
The full error means the directory indicated by jdbc:hsqldb:file:home/user/db/ does not exist, or it is a read-only directory where the .lck file cannot be created.
In order to narrow down the cause, you should find the correct absolute path by trying to list the existing .script file using a Java file method. An absolute path starts with the / character. You can then try to open the database as readonly, which does not create a .lck file. If this is successful, you can try to open the database normally.
I am trying to upload a text blob to azure storage blob using the following code:
public static final String storageConnectionString = "DefaultEndpointsProtocol=http;"
+ "AccountName=MY_STORAGE_ACNT;"
+ "AccountKey=[MYKEY]";
CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString);
CloudBlobClient blobClient = account.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("ubiety");
container.createIfNotExists();
BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER);
container.uploadPermissions(containerPermissions);
CloudBlockBlob blob1 = container.getBlockBlobReference("storage_name");
blob1.uploadText("Hello, World1");
This is a mere copy paste of the sample at BlobBasics Sample, still
I get the error
StorageKey is not a valid Base64 Encoded string.
Can someone please help. I am very sure, i am using the correct key provided at the azure portal
Thank you.
I got this message as well and it turned out I was using the wrong key. I was using the shared access signature obtained from the azure storage explorer. That's wrong. You need to grab the key from the azure portal. Go to the dashboard.
Select your storage account. You can then select "Access keys". Just pick the top key.
Then run code like this ( Scala, but Python is possible too )
var storage_account_name:String = = "storageaccountname"
// This is key1 from access keys in my user interface
var storage_account_access_key: String = "UU8udCiTs/3CEmjH3xVVFtSR7EAWZifGlSf3QoNNUDYL2GjxQ4mQ3GhuoZvO8G/eO9Z+SgY1uXrVBGHBc5u7tA=="
spark.conf.set(
"fs.azure.account.key."+storage_account_name+".blob.core.windows.net",
storage_account_access_key)
spark.read.format("csv").load("wasbs://blobname#storageaccountname.blob.core.windows.net/csvfile.csv")
In the example storageaccountname is the name of my storage account. blobname is the name of the blob in the storage account.
Good luck
Looking at the sample link you've given it looks like you're using the Java Storage library rather than the Android Storage library. If you use the Android storage library and it's associated samples that should work correctly.
Azure Account Keys with forward slash (/) does not work. See https://github.com/Azure/azure-xplat-cli/issues/3135
What I did -
com.microsoft.azure.storage.StorageCredentialsAccountAndKey creds =
new StorageCredentialsAccountAndKey(accountName, key_with_slash);
com.microsoft.azure.storage.CloudStorageAccount account = new CloudStorageAccount(creds, false);
on linux you can use the base64 program and it worked for me. Do not include the % at the end
echo -n '<ONE OF YOUR ACCESS KEY FROM BLOB STORAGE ACCOUNT>' | base64 -w 0
In BaseDemoActivity.java from Google Drive Demo app
https://github.com/googledrive/android-demos/blob/master/src/com/google/android/gms/drive/sample/demo/BaseDemoActivity.java
what i have replace in EXISTING_FOLDER_ID,EXISTING_FILE_ID,EXTRA_ACCOUNT_NAME
Please provide steps to get this values
/**
* DriveId of an existing folder to be used as a parent folder in
* folder operations samples.
*/
public static final String EXISTING_FOLDER_ID = "????";
/**
* DriveId of an existing file to be used in file operation samples..
*/
public static final String EXISTING_FILE_ID = "????";
/**
* Extra for account name.
*/
protected static final String EXTRA_ACCOUNT_NAME = "????";
Thanks
The first part, EXISTING_FOLDER_ID,EXISTING_FILE_ID, is answered in SO 21800257, but be careful.
You can't just go to a web Drive interface, create a file, copy/paste its resource id ... Google Drive Android API (GDAA) supports only FILE scope, so only files, folders created by your Android App are eligible.
EXTRA_ACCOUNT_NAME is a name of your Google (gmail) account (myaccount#gmail.com). That's the one you would need here:
GoogleApiClient mGac = new GoogleApiClient.Builder(contex)
.addApi(com.google.android.gms.drive.Drive.API)
.addScope(com.google.android.gms.drive.Drive.SCOPE_FILE)
.setAccountName(EXTRA_ACCOUNT_NAME)
.addConnectionCallbacks(context).addOnConnectionFailedListener(context)
.build();
but I'm not sure the demo even addresses this.
You would use it if your Android App allowed switching between different accounts.
I am trying to design an app which downloads the appropriate sound files from my Google cloud storage account. The app does not access the users account but my own.
My reading has led me to believe that the most appropriate model is
The Service account
https://code.google.com/p/google-api-java-client/wiki/OAuth2#Service_Accounts
Unfortunately the developers have decided not to provide an example with Android. They do provide a nice example with just plain Java, which works
http://samples.google-api-java-client.googlecode.com/hg/storage-serviceaccount-cmdline-sample/instructions.html?r=default
I tried to adapt this for Android and have run into problems.
GoogleCredential credential =
new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY).setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(STORAGE_SCOPE)
.setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();
In Google's example they pass the key.p12 file , However on Android when I put the file in the res/raw folder it seems the only way I have of accessing it is as an input stream. I can't find an elegant way to get a file to pass to JSON.
This all leads me to believe I must be doing something wrong.
Should I be using the key.p12
Should I be using the "service account model".
Is there an example out there /
Thanks
Ryan
An Update
I managed to achieve my goal of getting it to work but my solution feels clunky to me and I am sure it is not the way intended
What I did was add the key.p12 as a raw/resource which I opened as as input stream. Which I then converted to the private key using the libraries as seen in the example.
http://www.flexiprovider.de/examples/ExampleSMIMEsign.html
My code looks like this
Security.addProvider(new de.flexiprovider.core.FlexiCoreProvider());
// Next, we have to read the private PKCS #12 file, since the the
// private key used for signing is contained in this file:
DERDecoder dec = new DERDecoder(getResources().openRawResource(
R.raw.key));
PFX pfx = new PFX();
try {
pfx.decode(dec);
SafeBag safeBag = pfx.getAuthSafe().getSafeContents(0)
.getSafeBag(0);
PKCS8ShroudedKeyBag kBag = (PKCS8ShroudedKeyBag) safeBag
.getBagValue();
char[] password = "my password from google api".toCharArray();
privKey = kBag.getPrivateKey(password);
new AsyncLoadStorage(this).execute();
} catch (ASN1Exception e) {
But the whole thing is ugly and I would like a cleaner solution
Google documentation is actually pretty misleading. They haven't updated their console links (keep on asking you to look for "register apps" link, which doesn't exist), and their JAVA api for GCS doesn't work in Android (GcsService service = GcsServiceFactory.createGcsService();). Seems like they expect you to access GCS from App engine only.
So, here's what one needs to do:
You probably don't want users to have to sign into GCS or Google (think of Snapchat app).
But you still want authentication, so your data isn't completely in public view; its only accessible through your apps.
You'd want to have a service account P2K file, which you can bundle along with app, so your users don't have to login anywhere.
From https://cloud.google.com/console/project, click Project > APIs & Auth > Credentials > Create new Client ID > Service Account. This would let you download P2K file.
Store this in res/raw/private_key.p2k, and then use the following code to authenticate your android app to query GCS.
This works without any problems for me:
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
Log.d("testing", "checking if I can create a credential");
httpTransport = AndroidHttp.newCompatibleTransport();
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(resources_.openRawResource(R.raw.gcs_privatekey),
"password".toCharArray());
PrivateKey key = (PrivateKey) keystore.getKey("privatekey", "password".toCharArray());
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountPrivateKey(key)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
// .setServiceAccountUser(SERVICE_ACCOUNT_EMAIL)
// .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build();
credential.refreshToken();
String URI = "https://storage.googleapis.com/" + BUCKET_NAME;
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl(URI);
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse response = request.execute();
String content = response.parseAsString();
Log.d("testing", "response content is: " + content);
new Storage.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName("appname").build();
Here is what I did to transform the inputStream key to a PrivateKey object :
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), MyClass.class.getResourceAsStream("/privatekey.p12"), "notasecret", "privatekey", "notasecret");
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_ID)
.setServiceAccountScopes(Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL))
//.setServiceAccountPrivateKeyFromP12File(f)
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.build();
I don't know your exact situation, but could you just make these files completely public so that no auth at all is required to download them?
In Android, how do I get the application's id programatically (or by some other method), and how can I communicate with other applications using that id?
If your are looking for the value defined by applicationId in gradle, you can simply use
BuildConfig.APPLICATION_ID
EDIT 2022:
As indicated in the comments, BuildConfig.APPLICATION_ID is deprecated, but for librairies only. In this case, BuildConfig.LIBRARY_PACKAGE_NAME should be used instead, as explained here.
Also, now, Context::getPackageName returns the value defined by applicationId in gradle, even if you have several flavors with different applicationId (with a unique namespace), see here.
If by application id, you're referring to package name, you can use the method Context::getPackageName (http://http://developer.android.com/reference/android/content/Context.html#getPackageName%28%29).
In case you wish to communicate with other application, there are multiple ways:
Start an activity of another application and send data in the "Extras" of the "Intent"
Send a broadcast with specific action/category and send data in the extras
If you just need to share structured data, use content provider
If the other application needs to continuously run in the background, use Server and "bind" yourself to the service.
If you can elaborate your exact requirement, the community will be able to help you better.
i'm not sure what "application id" you are referring to, but for a unique identifier of your application you can use:
getApplication().getPackageName() method from your current activity
For getting AppId (or package name, how some says), just call this:
But be sure that you importing BuildConfig with your app id packages path
BuildConfig.APPLICATION_ID
Package name is your android app id .
String appId = BuildConfig.APPLICATION_ID
Or
https://play.google.com/store/apps/details?id=com.whatsapp
App Id = com.whatsapp
Else you can get id of process your application runs in:
final static int android.os.Process.myPid()
Returns the identifier of this process, which can be used with killProcess(int) and sendSignal(int, int).
I am not sure what you need the app/installation ID for, but you can review the existing possibilities in a great article from Android developers:
http://android-developers.blogspot.com/2011/03/identifying-app-installations.html
To sum up:
UUID.randomUUID() for creating id on the first time an app runs after installation and simple retrieval afterwards
TelephonyManager.getDeviceId() for actual device identifier
Settings.Secure.ANDROID_ID on relatively modern devices
Step 1: Open the Google Play Store
Step 2: Open any App in App Store
Example: facebook
Step 3: Click on any App and Look at the Browser link and At the End id=com.facebook.katana&hl=en will be there and this is your Apps Unique Id.
The PackageInfo.sharedUserId field will show the user Id assigned in the manifest.
If you want two applications to have the same userId, so they can see each other's data and run in the same process, then assign them the same userId in the manifest:
android:sharedUserId="string"
The two packages with the same sharedUserId need to have the same signature too.
I would also recommend reading here for a nudge in the right direction.
If the whole purpose is to communicate data with some other application, use Intent's sendBroadcast methods.
If you are using the new** Gradle build system then getPackageName will oddly return application Id, not package name. So MasterGaurav's answer is correct but he doesn't need to start off with ++
If by application id, you're referring to package name...
See more about the differences here.
** not so new at this point
++ I realize that his answer made perfect sense in 2011
Android App ES File Explorer shows the Android package name in the User Apps section which is useful for Bitwarden. Bitwarden refers to this as "android application package ID (or package name)".
To track installations, you could for example use a UUID as an identifier, and simply create a new one the first time an app runs after installation. Here is a sketch of a class named “Installation” with one static method Installation.id(Context context). You could imagine writing more installation-specific data into the INSTALLATION file.
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
Yon can see more at https://github.com/MShoaibAkram/Android-Unique-Application-ID
This is now deprecated you should use BuildConfig.LIBRARY_PACKAGE_NAME as answered here