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"
Related
I want to save the logs generated by my application locally on the android device and view them in an instance of a crash.
Using the "Take Bug Report" under the developer options gives the entire system logs which are irrelevant to me. I am looking only for those logs created by my application when it runs.
Is there any application that does this? Or are there any libraries I could include in my application code to satisfy my requirement?
You may just add firebase to your project, and everything will be done automatically.
Or if need it to be "locally", can use the Thread.UncaughtExceptionHandler to save crash log. Register it when your application onCreate.
private static UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
public static void registerUncaughtExceptionHandler() {
mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
// Save Log
saveLog(ex);
// Throw system
mDefaultUncaughtExceptionHandler.uncaughtException(thread, ex);
}
});
}
private static void saveLog(Throwable exception) {
try {
String stackTrace = Log.getStackTraceString(exception);
// Save it to SharedPreferences or DB as you like
} catch (Exception e) {
}
}
Then can extract the last crash log, submit to your server or display in logcat when app starts.
It is much better to use Third Party libraries such as Firebase Crashlytics or Sentry Crash Report or AppMetrica for crash reports.
just add these libraries and make an account on one of these sites, then you can have a full report of crashes if happen.
but if you want to save the logs on the device, you can refer to this question :
Saving Logcat to a text file in Android Device
You can try this
fun writeLog(context: Context) {
try {
val path = File(context.filesDir, "log_files")
if (!path.exists()) {
path.mkdir()
}
val fileName = "your_filename.txt"
Runtime.getRuntime().exec("logcat -v time -f $fileName")
} catch (e: IOException) {
}
}
Or you can change logcat command based on your requirements: refer to this https://developer.android.com/studio/command-line/logcat
You can check it at data/data/{applicationId}/files/log_files/
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.
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
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.
I cannot make an Android phonegap plugin work. Not even a single one of the examples I found nor my pathetic failures trying to create one by myself. I first tried with Tutorials like this one. They don't work for me. I always end up with a Cannot call method of undefined error.
So I tried something ready. Got this project from github. It's just a simple plugin to show a toast. I checked everything that i learned on the tutorials:
//the package name in the java
package com.phonegap.toast;
//my class extends Plugin and has a simple show toast method.
public class Tutorial extends Plugin {
#Override
public PluginResult execute(String cmd, JSONArray args, String callback) {
if(cmd.equals("toast"))
{
return showToast(args);
}
return null;
}
private PluginResult showToast(JSONArray args) {
final String message;
try {
message = args.getString(0);
ctx.runOnUiThread(new Runnable()
{
public void run() {
Toast myToast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT);
myToast.show();
}
});
return new PluginResult(PluginResult.Status.OK);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
}
the plugin is defined in res/xml/plugins.xml
plugin name="Tutorial" value="com.phonegap.toast.Tutorial"
and no, if i put it on rex/xml/config.xml it also doesn't work
Last, the method that calls the plugin:
function createToast() {
// i also tried window.Tutorial.showToast('Hello AndroidOpen'); with no success
window.plugins.Tutorial.showToast('Hello AndroidOpen');
}
And here I get the same error again.
10-22 15:39:07.770: E/Web Console(2885): Uncaught TypeError: Cannot call method 'showToast' of undefined at file:///android_asset/www/main.js:123
Any enlightened soul can explain to me what I'm doing wrong? I've been trying this for days, with many different plugins, both my own and even this ones and I can't find out what is it.
Okay, here are a few things that are probably tripping you up. First if the config.xml file exists in res/xml then it will take precedence over plugins.xml. So you will need to add your plugin line to config.xml instead.
Make sure you are including the .js file for your Toast plugin.
Third, window.plugins has been deprecated away so you may need to modify the .js if you are using PhoneGap 2.0.0 or better. Check out my blog post on the topic. The root change is that you now need to new PluginName in your JS as it is no longer put in window.plugins by default.