Android 5.0 (L) Service Intent must be explicit in Google analytics - android-5.0-lollipop

My code worked in <5 but in Android 5.0 I'm running into an issue that I don't quite understand.
10-23 10:18:18.945: E/AndroidRuntime(8987): java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.gms.analytics.service.START (has extras) }
My code works, even now, on 4.4.4 and below. So what do I need to do? I'll post relative code below. Also, during my googling I found this post about java.lang.IllegalArgumentException: Service Intent must be explicit in regard to Android 5.0 but I don't understand what it means.
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxxxx.android.phone.xxxxx"
android:versionCode="3"
android:versionName="v1.2.4065" >
<uses-sdk android:minSdkVersion="12"
android:targetSdkVersion="21" />
<!-- Required for Google Analytics -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- For push notifications (GCM) -->
<permission android:name="xxxxx.android.phone.xxxxx.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="xxxxx.android.phone.xxxxx.permission.C2D_MESSAGE" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM connects to Google Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- GCM - We handle notifications differently if the app is running -->
<uses-permission android:name="android.permission.GET_TASKS" />
<!-- Caching -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- The event subscribe button adds events to the calendar -->
<!-- <uses-permission android:name="android.permission.WRITE_CALENDAR" /> -->
<!-- <uses-permission android:name="android.permission.READ_CALENDAR" /> -->
<supports-screens
android:resizeable="true"
android:smallScreens="false"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true" />
<application
android:name="xxxxx.xxxxxApplication"
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:allowBackup="true"
android:largeHeap="true" >
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="xxxxx.android.phone.xxxxx" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="xxxxx.android.phone.xxxxx" />
</intent-filter>
</receiver>
<receiver
android:name="xxxxx.ConnectivityReceiver"
android:enabled="false" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<activity
android:name=".SplashActivity"
android:configChanges="locale|orientation"
android:theme="#style/Theme.Splash"
android:screenOrientation="portrait"
android:noHistory="true" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:label="#string/app_name"
android:theme="#style/Theme"
android:windowSoftInputMode="adjustPan|stateVisible"
android:name=".LoginActivity"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".MainActivity"
android:theme="#style/Theme"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateVisible" />
<activity
android:name=".CountryPickerActivity"
android:theme="#style/Theme.Floating"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateVisible" />
<activity
android:name=".EventPickerActivity"
android:theme="#style/Theme.Floating"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateVisible" />
<activity
android:name=".TutorialActivity"
android:theme="#style/Theme.Transparent"
android:configChanges="locale|orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".VideoPlayerActivity"
android:theme="#style/Theme"
android:configChanges="orientation|screenSize" />
<service android:name=".GCMIntentService" android:enabled="true" />
<meta-data android:name="com.crashlytics.ApiKey" android:value="xxxxxxxxxxxxxxxx"/>
</application>
</manifest>
GCMIntentService.java
public class GCMIntentService extends GCMBaseIntentService {
private static final int ATTEMPTS_MAX = 3;
final static boolean USE_DEV = false;
final static String XXXXX = "https://xxxxx/api.php";
final static String XXXXX = "http://dev.xxxxx/api.php";
final static String SUBSCRIPTION_KEY = "xxxxxxxxxxxxxxx"; // unique per app
public GCMIntentService() {
super(xxxxxx.SENDER_ID);
if(GCMIntentService.USE_DEV) {
host = XXXXX;
} else {
host = XXXXX;
}
}
...
}
** EDIT **
The more I look at this issue the more I think it's not in GCMIntentService.java. I should have posted my stack trace before which is:
10-23 13:17:08.095: E/AndroidRuntime(10560): FATAL EXCEPTION: GAThread
10-23 13:17:08.095: E/AndroidRuntime(10560): Process: xxxxx.android.phone.xxxxx, PID: 10560
10-23 13:17:08.095: E/AndroidRuntime(10560): java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.gms.analytics.service.START (has extras) }
10-23 13:17:08.095: E/AndroidRuntime(10560): at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1674)
10-23 13:17:08.095: E/AndroidRuntime(10560): at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1773)
10-23 13:17:08.095: E/AndroidRuntime(10560): at android.app.ContextImpl.bindService(ContextImpl.java:1751)
10-23 13:17:08.095: E/AndroidRuntime(10560): at android.content.ContextWrapper.bindService(ContextWrapper.java:538)
10-23 13:17:08.095: E/AndroidRuntime(10560): at com.google.analytics.tracking.android.AnalyticsGmsCoreClient.connect(AnalyticsGmsCoreClient.java:82)
10-23 13:17:08.095: E/AndroidRuntime(10560): at com.google.analytics.tracking.android.GAServiceProxy.connectToService(GAServiceProxy.java:279)
10-23 13:17:08.095: E/AndroidRuntime(10560): at com.google.analytics.tracking.android.GAServiceProxy.createService(GAServiceProxy.java:163)
10-23 13:17:08.095: E/AndroidRuntime(10560): at com.google.analytics.tracking.android.GAThread.init(GAThread.java:95)
10-23 13:17:08.095: E/AndroidRuntime(10560): at com.google.analytics.tracking.android.GAThread.run(GAThread.java:493)
So I'm going to try to run GA as explicit intent.

If you're trying to use Google's Licensing mechanism, solution that worked for me:
// explicit Intent, safe
Intent serviceIntent = new Intent(ILicensingService.class.getName());
serviceIntent.setPackage("com.android.vending");
boolean bindResult = mContext.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
This is located in com/google/android/vending/licensing/LicenseChecker.java. Do a search for "Base64.decode("
Edit:
Adding reference to Google Licensing java file that has to be patched:
com.google.android.vending.licensing.LicenseChecker.checkAccess(LicenseChecker.java:150)
patch:
new String(
- Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))),
+ Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")))
+ .setPackage("com.android.vending"), // this fix the 'IllegalArgumentException: Service Intent must be explicit'
this, // ServiceConnection.
Source: https://code.google.com/p/android/issues/detail?id=78505#c19

Since Android 5.0 (Lollipop) bindService() must always be called with an explicit intent. This was previously a recommendation, but since Lollipop it is enforced: java.lang.IllegalArgumentException: Service Intent must be explicit
is thrown every time a call to bindService() is made using implicit intents.
The difference between implicit and explicit intents is that the latter specifies the component to start by name (the fully-qualified class name).
See the documentation about intent types here.
The issue you are having is due to not having upgraded to a newer version of the google libraries, which comply with Android's restrictions on implicit intents when binding a service on Android 5 Lollipop.
To fix the issue, you can upgrade the library to a newer version if available, or update the library code yourself and build your project with the modified version.
If there's no suitable library upgrade in the general case, you need to modify the source code (in your case com.google.analytics.tracking.android.AnalyticsGmsCoreClient.connect()) to call intent.setPackage(packageName) before calling bindService() where intent is the first argument of the bindService() call and packageName is the name of the package containing the service the code is attempting to start (in your case "com.google.android.gms.analytics").
You can use this code as an example how to do this: Unity's updated version of the Google Licensing Library (LVL) which calls bindService with an explicit intent and does not result in IllegalArgumentException.
Yet another way to get around the problem is to rebuild your project and the google libraries using targetSDK no later than 19. This will make it run without crashing on Lollipop but is the less secure option and prevents you from using SDK functionality introduced in later versions (for Android 5).

Migration from Google Analytics v2 to v3 solve the problem for me.

I was just having this problem myself. The issue lies within your activity that is starting your service.
Basically, an explicit intent names the service directly in the intent when the service is started. See http://developer.android.com/guide/components/intents-filters.html for a more in-depth explanation.
Since, you don't have your activity code posted, I don't know how you're starting it now, but it should probably look something like this:
Intent startIntent = new Intent(this, ServiceToStart.class);
this.startService(startIntent); // or bindService(...)

I used this and it works great
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
//Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
//Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
//Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
//Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
//Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}

I'm working on a project where we want to allow users to use older devices. I came up with the same solution as the one mentioned in Marias answer, however I've added a conditional statement for the setPackage call since it is only available in API 4 (Ice Cream Sandwich == SDK 14) and above. If developing for versions below that I reckon you don't need to include the setPackage call.
In function com.google.android.vending.licensing.LicenseChecker.checkAccess(callback)
Intent serviceIntent = new Intent(new String(
Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
serviceIntent.setPackage("com.android.vending");
}
boolean bindResult =
mContext.bindService(
serviceIntent,
this, // ServiceConnection.
Context.BIND_AUTO_CREATE);

If you want to start a service which is in another application.you can use this:
Intent serviceIntent = new Intent("action name for the service");
serviceIntent.setPackage("the PackageName for which the service in)");//the destination packageName
context.startService(serviceIntent);

This worked for me..This worked in lollipop using android sdk 21..
Intent intent = new Intent(this, Class.forName(ServiceClassName.class.getName()));
bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);

For PhoneGap/Cordova users who are seeing this error, it's because the semi-official GAPlugin uses the deprecated Google Analytics v2 lib. khalidb91 forked it and updated to v3 which as of this writing hasn't been merged into the semi-official plugin. Grab the code from his fork, drop it in as a direct replacement to plugins/com.adobe.plugins.GAPlugin and no more crashes. Thanks khalidb91!
https://github.com/khalidb91/GAPlugin

This works for me:
Intent intent = new Intent(ACTION);
intent.setPackage(context.getPackageName());
context.startService(intent);

If you are trying to start service, try it this way:
var intent = new Intent (this,typeof(MyBoundService));
var serviceConnection = new MyBindServiceConnection (this);
BindService (intent, serviceConnection, Bind.AutoCreate);

Related

How can I use the variable {server.name} in services-config.xml from AIR?

I am converting an application from Flex/Flash to Flex/AIR. The application does messaging. I use the services-config.xml file to define channels & endpoints.
When using the endpoint definition in the services-config.xml I typically use;
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://{server.name}:{server.port}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<!-- <legacy-collection>true</legacy-collection> -->
</properties>
</channel-definition>
<channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
<endpoint uri="rtmp://{server.name}:1935" class="flex.messaging.endpoints.RTMPEndpoint"/>
</channel-definition>
</channels>
When running in AIR this is translated to the name of the SWF file (minus the first character oddly). I need to define at runtime the name of the server.
I have tried the following code in my creation complete section of the application;
RootDomain = "http://192.168.144.190/";
if (bolTestMode == false)
{
var strRTMPuri:String = RootDomain.substr(0, RootDomain.length - 1) + ":1935";
strRTMPuri = strRTMPuri.toLowerCase().replace("http:","rtmp:");
ServerConfig.getChannel("my-rtmp").uri = strRTMPuri;
ServerConfig.getChannel("my-amf").uri = RootDomain.substr(0, RootDomain.length - 1) + ":80";
}
Which does not seem to work.
The only thing which does seem to work is changing the services-confg.xml file to;
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://192.168.144.190:{server.port}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<!-- <legacy-collection>true</legacy-collection> -->
</properties>
</channel-definition>
<channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
<endpoint uri="rtmp://192.168.144.190:1935" class="flex.messaging.endpoints.RTMPEndpoint"/>
</channel-definition>
</channels>
and then compiling the application. Unfortunately this means that the production version of the application will need to be compiled with a different services-config.xml file, from testing.
What i am looking for/need is a method to define the server & ports at runtime.
I was almost there when I posted the question, but I forgot a little piece.
The way I resolved it is by modifying the ServerConfig at runtime using using this in my Action Script.
ServerConfig.getChannel("my-amf").uri = "http://Myserver.com:80/gateway,aspx";
ServerConfig.getChannel("my-rtmp").uri = "http://Myserver.com:1935";

Fix WP Bouncing IBM MobileFirst 6.3

I found the plugin to fix WP bouncing in cordova :
https://github.com/vilic/cordova-plugin-fix-wp-bouncing
I want to implement the plugin into my MFP project.
Native Code :
void border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
browser.InvokeScript("eval", "FixWPBouncing.onmanipulationcompleted()");
}
Javascript Code :
exports.onmanipulationcompleted = function () {
exports.target = null;
};
exports.fix = function (target) {
if (!POINTER_DOWN) { return; }
if (!(target instanceof HTMLElement) && target.length) {
target = target[0];
}
target.addEventListener(POINTER_DOWN, function () { exports.target = target; }, false); };
plugin.xml :
<js-module src="www/fix-wp-bouncing.js" name="fix-wp-bouncing">
<clobbers target="FixWPBouncing" />
</js-module>
<!-- windows phone 8 -->
<platform name="wp8">
<config-file target="config.xml" parent="/*">
<feature name="FixWPBouncing">
<param name="wp-package" value="FixWPBouncing"/>
<param name="onload" value="true" />
</feature>
</config-file>
How to call :
// call fix after deviceready.
var wrapper = document.getElementById('an-element-that-scrolls');
FixWPBouncing.fix(wrapper);
// I don’t have any idea where i must write this code below :
declare module FixWPBouncing {
/** when target is a JQuery, it process the first element only. */
export function fix(target: HTMLElement|JQuery): void;
}
From the code above, this is my explanation :
call FixWPBouncing.fix(wrapper); => it will call the javascript function exports.fix, The purpose of this function is adding the event listener when we touch the element.
The listener in the native code void border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) will trigger the javascript code exports.onmanipulationcompleted
<param name="onload" value="true" /> => The purpose of this configuration, is autoload the Native Code, so i don’t need to call cordova.exec
Because of that, i think to integrate the javascript code and the native code, i will need :
<js-module src="www/fix-wp-bouncing.js" name="fix-wp-bouncing">
<clobbers target="FixWPBouncing" />
</js-module>
So the native code listener will always trigger the javascript code.
I feel confused to change the logic like : https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-6-3/adding-native-functionality/windows-phone-8-adding-native-functionality-hybrid-application-apache-cordova-plugin/
Because from that link, we call the native with cordova.exec.
Not with autoload and automatically trigger the javascript code.
Please correct me if i’m wrong.
Do you have any idea to implement : https://github.com/vilic/cordova-plugin-fix-wp-bouncing in the MFP project ?
If you are implementing a Cordova plug-in in a Hybrid application, you must follow the instructions as provided in the MobileFirst Platform Developer Center tutorial.
Implementing it based on other instructions is untested/supported.
Of course, you can always choose to use a "pure" Cordova application in MobileFirst Platform Foundation 7.1, negating the need to go through anything related to MPF and instead follow standard Cordova procedures.

Google Drive SDK : Drive QuickStart App example doesn't work on Android

The Drive QuickStart App example doesn't work on Android (https://developers.google.com/drive/quickstart-android).
I have a Note 2 running on Android 4.1.2. I followed all the steps in the tutorial (using eclipse + ADT + google console) and have spent over 30 hours on it.
There is a "ClassNotFoundException" in the following line:
File file = service.files().insert(body, mediaContent).execute();
I found that the exception occurs in Drive.Files.Insert.execute() part.
Has anyone been able to get this camera app to work? I watched the video tutorial for this app, and even the developer says the app is only "probably going to work"...
Is there a confirmed-working Drive SDK app out on the internet? All I want to do is to download a simple google spreadsheet from google drive.
Other things that I have tried:
- The DrEdit sample app given by Google is also not syncing properly with google drive.
- I also can't find a working sample app on the Google Document List API website.
I believe that accessing Google Drive from Android should be a simple task that comes with an example...Otherwise, people might as well use DropBox.
Thanks!
While I was looking how to open a single spreadsheet from Drive, I went thru the same QuickStart app and I was using Eclipse Juno, Windows 7, 64 bit. I watch both videos, the second being Integerate with the Android Drive App
I used the steps from both, especially in my manifest xml. I had to go the video twice to make sure I had all of the steps. I had to add the user-feature to my manifest.
<uses-feature android:name="android.hardware.camera" />
There were a couple of other things I found. I was unable to run it on the emulator at all. Running it on the phone in debug mode didn't initially work either, it could get access to the phone's SD card (obviously). I copied the APK on to the phone and installed it, make sure your security settings are relaxed. It worked on my phone (Jellybean Droid Razr) when not tethered via ADB.
Here's most of my manifest. Note you have to replace the 'YOURCLIENTID' with yours from the API Console. I only used the first set of numbers, nothing after the '-', i.e. 123456789-blah, blah. Just the 123456789.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.birdsall.tda"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:exported="true" >
<meta-data android:name="com.google.android.apps.drive.APP_ID" android:value="id=YOURCLIENTID" />
<intent-filter>
<action android:name="com.google.android.apps.drive.DRIVE_OPEN" />
<data android:mimeType="application/vnd.google-apps.drive-sdk.YOURCLIENTID" />
<data android:mimeType="image/png" />
<data android:mimeType="image/jpeg" />
<data android:mimeType="image/jpg" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".ActivitySearch" />
<activity
android:name="com.birdsall.tda.ActivityMain"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ActivityTakePhoto" >
</activity>
<provider
android:name="com.birdsall.tda.TDAProvider"
android:authorities="com.birdsall.tda.contentprovidertda"
android:exported="true"
android:readPermission="true"
android:writePermission="true" />
<activity
android:name=".ActivitySearch"
android:label="Rule Search"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
</application>
</manifest>
I think I only changed the class name of the activity, otherwise I didn't have to change any of the java code. Here's my activity:
package com.birdsall.tda;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.widget.Toast;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.FileContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
public class ActivityTakePhoto extends Activity {
static final int REQUEST_ACCOUNT_PICKER = 1;
static final int REQUEST_AUTHORIZATION = 2;
static final int CAPTURE_IMAGE = 3;
private static Uri fileUri;
private static Drive service;
private GoogleAccountCredential credential;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
credential = GoogleAccountCredential.usingOAuth2(this, DriveScopes.DRIVE);
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
credential.setSelectedAccountName(accountName);
service = getDriveService(credential);
startCameraIntent();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == Activity.RESULT_OK) {
saveFileToDrive();
} else {
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
break;
case CAPTURE_IMAGE:
if (resultCode == Activity.RESULT_OK) {
saveFileToDrive();
}
}
}
private void startCameraIntent() {
String mediaStorageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getPath();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
fileUri = Uri.fromFile(new java.io.File(mediaStorageDir + java.io.File.separator + "BCM_IMG_"
+ timeStamp + ".jpg"));
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(cameraIntent, CAPTURE_IMAGE);
}
private void saveFileToDrive() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
// File's binary content
java.io.File fileContent = new java.io.File(fileUri.getPath());
FileContent mediaContent = new FileContent("image/jpeg", fileContent);
// File's metadata.
File body = new File();
body.setTitle(fileContent.getName());
body.setMimeType("image/jpeg");
File file = service.files().insert(body, mediaContent).execute();
if (file != null) {
showToast("Photo uploaded: " + file.getTitle());
startCameraIntent();
}
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
private Drive getDriveService(GoogleAccountCredential credential) {
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
.build();
}
public void showToast(final String toast) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), toast, Toast.LENGTH_LONG).show();
}
});
}
}
Hope this helps.
Not sure if this will help you much, but yes, I got the QuickStart app working with Eclipse/Kepler. I had a lot of problems with Eclipse/Juno and also read posts about how Juno and ADT don't mesh quite right.
I am presently using portions of their code to upload a text file from the phone to Drive. I have a Nexus 4 running 4.2.2. I note that the minimum API level for the Quickstart app is 4.2 so it's possible that this is where the problem lies. Have you tried it on a 4.2 emulator rather than your Note?
And yes, it is a simple task, but it has to be set up exactly right. Drive has its own way of dealing with files (i.e. does not overwrite files with the same name, just creates another one).

How to trust a self-signed certificate in a windows store app

I am trying to override the certificate validation in a Windows Store App to accept a self-signed certificate on two external services (using HttpClient) to allow the Windows 8 app to accept the certificates and establish a trust relationship for SSL
EDIT:
I implemented the approach documented here : Installing certs by using the appmanifest
and added the relevant .cer files to my application and ensured they are 'Content' and 'Copy Always'.
My package.appxmanifest Extensions section looks like this:
<Extensions>
<Extension Category="windows.certificates">
<Certificates>
<Certificate StoreName="TrustedPeople" Content="Assets\ReportingServices.cer" />
<Certificate StoreName="TrustedPeople" Content="Assets\Crm.cer" />
<Certificate StoreName="CA" Content="Assets\DigiCertHighAssurance.cer" />
<TrustFlags ExclusiveTrust="true" />
<SelectionCriteria AutoSelect="true" />
</Certificates>
</Extension>
but this still does not work.
I have tried putting the app certificates in the 'Root' StoreName but still no success. Does anyone have any ideas why this might not work please?
This is a bit of old one, but seeing as there are quite a few watchers I will give my solution.
// Create the httpClient and send the request
HttpBaseProtocolFilter aHBPF = new HttpBaseProtocolFilter();
// If you want to ignore expired Certs
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
// Untrused because this is a self signed cert that is not installed
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
// Host names and certs names may not match
aHBPF.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
HttpClient httpClient = new HttpClient(aHBPF);
HttpResponseMessage response = await httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token);
Just to save your time. I got to resolve this for 2 days of trial and error. Here you can solve it.
Add the .cer file to your project, Make the build action as "Content", copy as newer
then add this to your app manifest
<Capabilities>
<Capability Name="sharedUserCertificates" />
<Capability Name="enterpriseAuthentication" />
<Capability Name="privateNetworkClientServer" />
<Capability Name="internetClient" />
</Capabilities>
<Extensions>
<Extension Category="windows.certificates">
<Certificates>
<Certificate StoreName="Root" Content="Certificates\vibeapi.cer" />
<TrustFlags ExclusiveTrust="true" />
<SelectionCriteria AutoSelect="true" />
</Certificates>
</Extension>
</Extensions>
and to your code behind you can now access the file using this
//Testing https connection
HttpClientHandler msgHandler = new HttpClientHandler();
using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient(msgHandler, true))
{
var HTTPSURL = new Uri("https://www.sample.net/");
var response = await httpClient.GetAsync(HTTPSURL);
var responseStr = await response.Content.ReadAsStringAsync();
}
see link for reference
help
It will work if you put cer file to the project root and change Content section in manifest file to Content="file.cer"

Adobe AIR 3.3 Update Framework

I am building an application in AIR (v3.3) using Flash (NOT Flex), and I am having trouble with the update framework. All the resources I have found are for older versions of AIR and / or refer to a Flex build.
It's the first time I have done this, and would really appreciate some guidance...
I have a simple test app - an image (which changes v1 to v2) and a text field.
This is what I have tried (following http://goo.gl/uvycg):
...
var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI();
...
public function checkForUpdate():void
{
...
appUpdater.updateURL = "http://mysite.com/updates/update-descriptor.xml";
appUpdater.isCheckForUpdateVisible = false;
appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate);
appUpdater.addEventListener(ErrorEvent.ERROR, onError);
appUpdater.initialize();
}
private function onUpdate(event:UpdateEvent):void
{
txt.text = 'onUpdate()';
appUpdater.checkNow();
}
private function onError(event:ErrorEvent):void {
txt.text = 'onError() ' + event.toString();
}
This is my updateDescriptor.2.5.xml:
<?xml version="1.0" encoding="utf-8"?>
<update xmlns="http://ns.adobe.com/air/framework/update/description/2.5">
<versionNumber>2.0</versionNumber>
<versionLabel>Beta 2</versionLabel>
<url>http://mysite.com/updates/UpdateTest.air</url>
<description>
<![CDATA[ update of bees. geometric growth. ]]>
</description>
So, the update descriptor with v2 of the app is on the server, I install and run v1 of the app, and all that happens is I see the onUpdate() message in my text field, and no update happens.
Where am I going wrong? Thanks!
Based on the documentation, it would appear that you need to make sure the current state of the ApplicationUpdaterUI is "ready," otherwise "checkNow()" will do nothing.
The most recent information on Adobe AIR updating can be found HERE. It applies across the board.