GoogleApiClient builder failing to build - android

I'm implementing Google Smart Lock into an app, and I was having no trouble with the Api Client building before. In fact, I was finalizing some syntax changes and cleaning up the code (didn't even touch the code that initializes the Api Client), and my app now dies when build() is called on the Api Client builder, due to abstract method zza. Here is the error being displayed:
java.lang.AbstractMethodError: abstract method "com.google.android.gms.common.api.Api$zze com.google.android.gms.common.api.Api$zza.zza(android.content.Context, android.os.Looper, com.google.android.gms.common.internal.zzq, java.lang.Object, com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks, com.google.android.gms.common.api.GoogleApiClient$OnConnectionFailedListener)"
at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source)
I have no clue why it suddenly started failing, and I couldn't find any changes I made that would have caused this error. Why isn't that abstract method being overridden? It's nested deep inside the library so I don't understand how I could have affected it.
I wrapped the Google Api Client calls in a manager I named CredentialManager. Here is the code I used to initialize the client:
public CredentialManager(ContextProvider contextProvider) {
mContextProvider = contextProvider;
mCredentialsApiClient = new GoogleApiClient.Builder(mContextProvider.getContext())
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(CredentialManager.TAG, "Api connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.i(CredentialManager.TAG, "Connection suspended with status " + i);
}
})
.enableAutoManage(mContextProvider.getContext(), connectionFailedResult -> {
if (connectionFailedResult.hasResolution()) {
try {
connectionFailedResult.startResolutionForResult(
mContextProvider.getContext(),
CredentialManager.Codes.RESOLVE_CONNECTION_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
// Unable to resolve, log error
Log.e(CredentialManager.TAG, "Resolution failed: " + e.getMessage());
}
} else {
//instead of displaying a dialog, just let the user continue and login manually.
Log.e(CredentialManager.TAG, "Connection failed: " + connectionFailedResult.getErrorMessage());
}
})
.addApi(Auth.CREDENTIALS_API)
.build();
}
If you have any insight as to what is causing this error, please let me know. I've scoured the internet for anyone that has seen something like this before, but couldn't find anything.

The issue was that some google play services dependencies had their versions updated and not the play-services-auth dependency used for google smart lock. The apk would compile fine, but crash when the Google Api Client was trying to initialize. The fix was to make all the versions the same, and invalidate cache + restart android studio, recompile, and run.

Related

Application Stopped on GPS Location Request Programmatically in Released APK

Update
Forgot to mention that this is a xamarin coding.
In case may help:
I changed my linking option in android options from none to sdk assemblies only
I also enabled proguard
I am having a problem regarding request of location but only in released apk, it always says application has stopped. I tried to debug it and found the part where exception occured. My application works well in debug mode so i'm clueless why it hit an exception during released apk testing. Tested using Asus zenfone 3 Nougat and OPPO lollipop, same result (failed on release, no issue on debug).
Here is part of my code
public void m4_setUpAllClickable()
{
try
{
btnEnableGPS.Click += delegate
{
enableGPSLocation();
};
}
catch { throw; }
}
private async void enableGPSLocation()
{
try
{
GoogleApiClient
googleApiClient = new GoogleApiClient.Builder(this)
.AddApi(LocationServices.API)
.Build();
googleApiClient.Connect();
LocationRequest
locationRequest = LocationRequest.Create()
.SetPriority(LocationRequest.PriorityHighAccuracy)
.SetSmallestDisplacement(LocationValues.minimunDisplacement)
.SetInterval(LocationValues.normalInterval)
.SetFastestInterval(LocationValues.fastestInterval);
LocationSettingsRequest.Builder
locationSettingsRequestBuilder = new LocationSettingsRequest.Builder()
.AddLocationRequest(locationRequest);
locationSettingsRequestBuilder.SetAlwaysShow(false);
//****** -> Problem Occur in this part and I don't know why since it is going straight to app has stopped instead of catch exception
LocationSettingsResult
locationSettingsResult = await LocationServices.SettingsApi.CheckLocationSettingsAsync(
googleApiClient, locationSettingsRequestBuilder.Build());
//****** -> ends here
if (locationSettingsResult.Status.StatusCode == CommonStatusCodes.ResolutionRequired)
{
locationSettingsResult.Status.StartResolutionForResult(this, 1);
}
else if (locationSettingsResult.Status.StatusCode == CommonStatusCodes.Success)
{
if (activitySource == "GPS Failed")
{
Intent intent;
intent = new Intent(this, typeof(Activity_AssignedList));
StartActivity(intent);
FinishAffinity();
}
else if (activitySource == "GPS Disabled")
{
Finish();
}
}
}
catch { throw; }
}
Have you added proguard rules to your project?If not, try this and rerun your release build
-keep public class com.google.android.gms.* { public *; }
-dontwarn com.google.android.gms.**
As #SushiHangover suggested on comment, I tried to change my application linking option from sdk assemblies only to none and it works well on released apk. I don't know why in this tutorial : https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/part_1_-_preparing_an_application_for_release/ it says to enable proguard and change the linking option from none to sdk assemblies only so I did to make my application smaller. It goes down from 66mb to 40mb so I thought its a good thing but the problem is that it cuts some classes my application need.
So far it's working without linking options and my proguard is still enabled. Thanks for the help !

TweetViewFetchAdapter.setTweetIds does not work in android

I want to display some tweets with the twitter API in my app. To do so I have fetched some tweet ids (which is working without any hassle) and use the TweetViewFetchAdapter adapter provided by the Twitter API to display my tweets.
The weird thing is: this has worked at some point! But then suddenly it stopped working (company app, multiple people working on the code but I haven't seen any changes to the twitter stuff in the time between working and not working)
The code is super straight forward taken from the official twitter site:
// fill the tweet adapter with the loaded tweet ids
#Override
protected void onPostExecute(List<Long> params){
if (params != null && params.size() > 0) {
adapter.setTweetIds(params,
new LoadCallback<List<Tweet>>() {
#Override
public void success(List<Tweet> tweets) {
Log.i("twitter", "Success!");
}
#Override
public void failure(TwitterException exception) {
Log.e("twitter", "Exception: " + exception.getMessage());
}
});
}
Log.i("twitter", "params.size = " + params.size() + "adapter.tweetCount = " + adapter.getCount());
}
(inside an AsyncTask). The adapter seems to fail to set the tweet ids as the debug output is I/twitter﹕ params.size = 10 adapter.tweet Count = 0
I tried to debug/have a log output in the success/failure callbacks, but I never got anything as if the methods would never be called (quite weird actually..)
Regarding log cat output I haven't seen any, but I'm afraid there is a little chance I might have messed it up as we just recently moved to Android Studio and I just can't get my head around some stuff there yet.
Issue was caused by an wrong version of okhttp / okhttp-urlconnection.
The weird part is that no debug messages was shown. This code resolved the debug message issue and helped resolve the issue overall:
final Fabric fabric = new Fabric.Builder(this)
.kits(new Twitter(authConfig))
.logger(new DefaultLogger(Log.DEBUG))
.debuggable(true)
.build();
Fabric.with(fabric);
Overall fix: change build.gradle:
dependencies {
// ...
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.3.0'
}
Original conversation: https://twittercommunity.com/t/adapter-settweetid-seems-to-be-unable-to-load-the-tweets-but-doesnt-fire-a-success-failure-callback/36506/13

How to retrieve crash reports from a wearable app?

Since Crashlytics doesn't work on wearable apps out of the box, I'm looking for an optimal way to intercept and report any potential exception thrown in the runtime. I wonder why they're not being automatically reported to Google Play Developer Console?
Google already announced that the future Android Wear update will have Wi-Fi support built-in, but even then, not every device is going to be equipped with the adequate hardware.
In that case, my initial idea was to create a subclass of Application and implement Thread.UncaughtExceptionHandler. Then, every exception would have to be marshalled and sent to a handset, using MessageApi. An extension of WearableListenerService on the handset would receive a message, unmarshal the exception and pass it to, for instance, Crashlytics.
However, that raises a few more questions. There's a risk that the Bluetooth connection between wearable and handset is disrupted, so all errors should be queued and stored on the wearable device's file system.
This seems like an overkill for a simple crash report. Is there an easier way to do this?
Don't use MessageApi for this purpose but DataApi. Then you don't have to worry about lost bluetooth connection.
The way it works:
when a crash occurs, set a DataItem with the crash on the wearable;
eventually it will be delivered to the Mobile device.
send the information about the crash from the Mobile and delete the DataItem.
More information here: http://developer.android.com/training/wearables/data-layer/index.html
Here's a draft of my solution. As #gruszczy suggested, I'm using DataApi.
Wearable Application:
public class WApplication extends Application
implements Thread.UncaughtExceptionHandler {
private static final String LOG_TAG = WApplication.class.getSimpleName();
private Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
...
#Override
public void onCreate() {
super.onCreate();
mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
#Override
public void uncaughtException(Thread thread, final Throwable throwable) {
Log.e(LOG_TAG, "Uncaught exception thrown.");
WearableService.launchService(throwable, WApplication.this);
mDefaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
}
Wearable Service:
public class WearableService extends Service {
...
public static void launchService(Throwable throwable, Context context) {
Intent startServiceIntent = new Intent(context, WearableService.class);
startService.putExtra(EXTRA_KEY_EXCEPTION, throwable);
context.startService(startServiceIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Throwable throwable = (Throwable) intent.getSerializableExtra(KEY_EXCEPTION);
sendExceptionToMobile(throwable);
return super.onStartCommand(intent, Service.START_REDELIVER_INTENT, startId);
}
private void sendExceptionToMobile(final Throwable throwable) {
if (throwable == null) {
return;
}
Log.d(LOG_TAG, "Sending exception to mobile...");
PutDataMapRequest putDataMapReq = PutDataMapRequest
.create(WearCommunicationConstants.PATH_EXCEPTION);
DataMap dataMap = putDataMapReq.getDataMap();
StringWriter sw = new StringWriter();
throwable.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
dataMap.putString(WearCommunicationConstants.KEY_STACK_TRACE, stackTrace);
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult =
Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(final DataApi.DataItemResult result) {
if (result.getStatus().isSuccess()) {
Log.d(LOG_TAG,
"DataItem synced: " + result.getDataItem().getUri());
} else {
Log.e(LOG_TAG,
"Failed to sync DataItem: " + result.getStatus().getStatusCode() + ", "
+ result.getStatus().getStatusMessage());
}
}
});
}
}
Mobile Service:
public class MobileService extends WearableListenerService {
...
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
Log.d(LOG_TAG, "Data changed, data event(s) received.");
for (DataEvent event : dataEvents) {
Log.d(LOG_TAG, "Data event type: " + event.getType());
switch (event.getType()) {
case DataEvent.TYPE_CHANGED:
DataItem item = event.getDataItem();
DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
switch (item.getUri().getPath()) {
case WearCommunicationConstants.PATH_EXCEPTION:
Log.e(LOG_TAG, "Received exception from a wearable device.");
String stackTrace = dataMap
.getString(WearCommunicationConstants.KEY_STACK_TRACE);
Utils.logWithCrashlytics(stackTrace);
break;
// ...
}
break;
case DataEvent.TYPE_DELETED:
// ...
}
}
}
}
Existing solutions require that the phone is currently in range. With Wear 2.0 providing for watch autonomy, we need to be able to store the crashes and send them over once we are connected. WearCrashReporter does exactly this.
We install a crash handler on the watch Virtual Machine. When a crash is caught, its trace and type are serialized to json, saved to the FileSystem, then sent with a service as a MessageApi Message when the phone is available. Upon reception by a WearableListenerService in the phone app it is deserialized and passed to the installed Phone Virtual Machine's crash reporter.
I solved this problem in following way:
Integrate this lib into your project. This lib will transmit all exceptions from wear app to mobile app.
If you don't use proguard - you can simple use ExceptionWear lib and log exceptions on mobile-app side into crashlytics.
otherwise
When you receive throwable on mobile-app side - you can log it into crashlytics, but there is a problem:
If we build mobile+wear application using android plugin feature we will have something like this:
dependencies {
compile 'com.google.android.gms:play-services:5.0.+#aar'
...lots of cool libs...
wearApp project(':wear')
}
and apply crashlytics plugin on both applications (mobile and wear) then during building wear application you can see that after proguard task and dex task (gradle tasks) crashlytics plugin doesn't store and upload Deobs and as a result - stacktraces are not remapped(retraced) on the crashlytics dashboard:
:wear:crashlyticsCleanupResourcesRelease//EXPECTED
:wear:crashlyticsUploadStoredDeobsRelease//EXPECTED
:wear:crashlyticsGenerateResourcesRelease//EXPECTED
:wear:generateReleaseResValues UP-TO-DATE
:wear:generateReleaseResources
:wear:mergeReleaseResources
:wear:processReleaseResources
:wear:generateReleaseSources
:wear:compileReleaseJava
:wear:proguardRelease
:wear:dexRelease//NO crashlytics store and upload Deobs tasks
:wear:processReleaseJavaRes UP-TO-DATE
:wear:shrinkReleaseResources
but when wear app is builded (wear ap is like dependency to mobile app) then mobile app build starts and during mobile build process crashlytics plugin works well:
:mobile:crashlyticsCleanupResourcesRelease//EXPECTED
:mobile:crashlyticsUploadStoredDeobsRelease//EXPECTED
:mobile:crashlyticsGenerateResourcesRelease//EXPECTED
:mobile:generateReleaseResValues UP-TO-DATE
:mobile:generateReleaseResources
:mobile:mergeReleaseResourcesknown
:mobile:processReleaseResources
:mobile:generateReleaseSources
:mobile:compileReleaseJava
:mobile:proguardRelease
:mobile:dexRelease
:mobile:crashlyticsStoreDeobsRelease//EXPECTED
:mobile:crashlyticsUploadDeobsRelease//EXPECTED
:mobile:crashlyticsCleanupResourcesAfterUploadRelease//EXPECTED
:mobile:lintVitalRelease
:mobile:compileReleaseNdk UP-TO-DATE
:mobile:processReleaseJavaRes UP-TO-DATE
:mobile:shrinkReleaseResources
So, during standard build process wear module deobs are not uploaded, but there is workaround:
if start build wear app separately and then manualy package wear apk in mobile module resources,
then wear deobs uploaded successfully and you can observe retraced crashes on dashboard.
But i personally don't like manual way of building apk, so i tried to do following : at first just build only wear app. deobs will uploaded to crashlytics. then run full build using 'wearApp project(':wear')' feature and looks like it works.
Anyway i am waiting for android-wear support by crashlytics out of the box.
It's possible to upload the deobs of mobile and wear within the build process.
Concept:
1. Ensure mobile and wear have unique mappings
2. Merge wear mappings into mobile mappings before upload
1. Configure proquard (usually proguard-rules.pro)
for wear add:
-useuniqueclassmembernames
for mobile add:
-useuniqueclassmembernames
-applymapping ../wear/build/outputs/mapping/release/mapping.txt
This change ensures you have unique names over mobile and wear by applying the mappings of the wear build to the mobile build.
2. Configure the build to merge mapping.txt
Add to build.gradle of mobile:
// allows to use Crashlytics also for wear by merging the mappings of wear into the
// mappings of mobile
//noinspection GroovyAssignabilityCheck
task mergeMappings(dependsOn: "transformClassesAndResourcesWithProguardForRelease") << {
File wearMappingFile = new File("wear/build/outputs/mapping/release/mapping.txt");
File mobileMappingFile = new File("mobile/build/outputs/mapping/release/mapping.txt");
if (wearMappingFile.exists() && mobileMappingFile.exists()) {
println("merge mapping.txt")
java.nio.file.Files.copy(wearMappingFile.toPath(),
new FileOutputStream(mobileMappingFile, true))
} // else we are on the wear build and the mobile build was not yet executed
}
afterEvaluate {
project.("crashlyticsStoreDeobsRelease").dependsOn(mergeMappings);
}
Appends the wear mappings to the mobile mappings before crashlyticsStoreDeobsRelease.

Google Analytics Mobile doesn't count

Got a strange thing going on, I recently started counting visitors of my app, it was working fine. Ater a while I saw that on Google Analytics, you can point out if it is a website or mobile. I made a new profile with 'mobile' selected, replaced the code in my app, but since then, it isn't counting anymore.. I waited more then 24 hours.
I use
mGATracker = GoogleAnalyticsTracker.getInstance();
mGATracker.startNewSession("UA-xxxxxxxx-x", this);
mGATracker.trackPageView("/About");
And dispatch in the onDestroy method:
#Override
public void onDestroy() {
try {
super.onDestroy();
mGATracker.dispatch();
mGATracker.stopSession();
} catch (Exception error) {
Log.e("<YOUR_TAG>", "onDestroy: " + error.toString());
}
}
Anybody else experienced this?
GA ver 1 requires 'website' type of panel.

Error integrating Aurasma: Resource Integrity check failed

I am trying to Integrating Aurasma in my application. All application work well but on Aurasma part when I launch it on Button Click IT throws a message on splash screen as "An error is occurred" and on Log Cat It shows "Resource integrity check failed" I am wondering why this is happening, I integrate aurasma on a separate application without any click event, it launches directly then it works but in side of my application its not working, why. I am sure about these points:
Make sure the SDK tools are version 14 or above.
Check the Eclipse project to make sure that AurasmaKernel is set as required on the build path
Check that the AurasmaKernel package has built properly in Eclipse (also try building it manually)
Make sure that the kernel is correctly extracted, and that your resources don't clash with any of the packaged library
But yet it not working same error message.
Code for launching Aurasma is below:
aurasmaIntent = AurasmaIntentFactory.getAurasmaLaunchIntent(HomeActivity.this,
getString(R.string.app_name), getString(R.string.app_version));
} catch (AurasmaLaunchException e) {
Log.e("AKTest", "Error getting intent", e);
showDialog(DIALOG_ERROR);
return;
}
if (DELAY_START) {
AurasmaSetupCallback callback = new AurasmaSetupCallback() {
#Override
public void onLoaded() {
dismissDialog(DIALOG_PROGRESS);
startActivity(aurasmaIntent);
}
#Override
public void onLoadWarning(final int code) {
Log.w("AKTest", "Preload warning: " + code);
}
#Override
public void onLoadFail(final int code) {
Log.e("AKTest", "Preload error: " + code);
dismissDialog(DIALOG_PROGRESS);
showDialog(DIALOG_ERROR);
}
};
showDialog(DIALOG_PROGRESS);
AurasmaIntentFactory.startAurasmaPreload(getApplicationContext(), aurasmaIntent,
callback);
} else {
startActivity(aurasmaIntent);
}
}
If you change some resource from Aurasma library(layout or string) you will get this error - "An error is occurred". Library checks resources on Aurasma start. Don't change or delete any files.
Another thing that can cause error is:
aurasmaIntent = AurasmaIntentFactory.getAurasmaLaunchIntent(HomeActivity.this,
getString(R.string.app_name), getString(R.string.app_version));
Here second parameter is userAgentName. This is the name of your app that you have from studio.aurasma.com. In "Make your own app" you can see the application name - this name is connected with your application but can be different.
check your minSdkVersion in the manifest
android:minSdkVersion="8"

Categories

Resources