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.
Related
I once wrote a quick ‘offline.html‘. Just be be sure I understood how offline PWA worked:
This is offline.html (My App Name)
I thought it worked as expected. So I deleted it and wrote a better one, with a back button, some info etc.
Now when this app is offline it starts on the page the manifest.json days, as expected.
However, if I try to refresh the page that spooky "offline.html" shows up. From nowhere.
I've tried to understand where it lurks, but I can't find it. (The new "offline.htmi" is there when I go to it in the web browser.)
I've tried Firefox offline on my mobile to see if the spoky "offline.html" jumps up there to. It does. 😐
I've cleared the cache in Chrome. The spoky "offline.html" is still there.
Any ideas?
(This is on Android 9)
Offline pages are not exactly stored in caches as regular cached items, there are stored quite differently, relative to the current installed service worker. I tried looking for an article to explain this more but can't walk around any currently.
However you'll have to unregister your service worker or learn how Updating service worker works,
The aim is to remove the lurking offline.html served to the new offline.html that exists.
This is what I finally landed on. It seems to work. The test for 404 is of course not optimal, but I leave it that way for now, hoping that the emerging standard will address this issue soon.
async function setupServiceWorker() {
let reg;
if (navigator.serviceWorker.controller) {
console.log("Active service worker found, no need to register");
// new Popup("registered service worker, .active.scriptURL", reg.active.scriptURL, null, true).show();
reg = await navigator.serviceWorker.getRegistration();
} else {
reg = await navigator.serviceWorker.register("service-worker.js", { scope: "./" });
console.log("Service-worker.js registered, scope: " + reg.scope);
}
try {
if (navigator.onLine) {
const newReg = await reg.update();
}
} catch (err) {
const is404 = err.message.match("404");
new Popup("err", is404 + " " + err.message).show();
if (is404) {
let wasUnregistered;
try {
wasUnregistered = await reg.unregister();
} catch (errUnreg) {
new Popup("unregister() service worker failed", errUnreg.message).show();
}
if (wasUnregistered) {
setTimeout(setupServiceWorker, 1000);
}
}
}
}
setTimeout(setupServiceWorker, 5000);
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.
We are using crashlyticsDidDetectCrashDuringPreviousExecution to detect java crashes and report them to our BI systems, but our app is mostly C++ and we are using crashlytics NDK, we can't find anything similar to crashlyticsDidDetectCrashDuringPreviousExecution.
Is there any way that we can actually detect an NDK crash when the app starts?
thanks
Oded
Mike from Fabric here.
Currently, there isn't a way to do this within Fabric or the SDK for an NDK crash.
NOTE: This works on older version only (Crashlytics 2.6.7 and CrashlyticsNDK 1.1.6)
I'm also looking for a solution for this.
We currently found a partial solution. I'm not sure how good it is, it's definitely not official, plus it's asynchronic (which we're trying to overcome by looping), but it's the best solution I found and it seems like it's working
Fabric.with(this, new Crashlytics.Builder().core(core.build()).build(), new CrashlyticsNdk(), new Crashlytics());
if (!userLeft) { // our handling to fix bug, see explanation below
new Thread(new Runnable() {
#Override
public void run() {
SessionEventData crashEventData = null;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000); // in ms
} catch (InterruptedException e) { }
crashEventData = CrashlyticsNdk.getInstance().getCrashEventData();
if (crashEventData != null)
{
// there was a crash!
// crash timestamp can be found at crashEventData.timestamp
break;
}
}
}
}).start();
}
Explaination for userLeft:
We had some bug with reporting crash for users that exited app, and this is the solution for that. We set this flag to true, and save it on the device (SharedPreferences). We do it on our main activity (which extends NativeActivity), on finish() func.
Code:
#Override
public void finish() {
// set some key such as USER_LEFT to TRUE
super.finish();
}
After that, just get that USER_LEFT value, assign it into userLeft param, and set it back to false on SharedPerferences.
Any insights about this solution?
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
I have to Users (User A and B) and one Chromecast device (C1).
User B starts a stream on C1.
User A connects to C1
Now User A should be able to control the stream running on C1. But every time I want to start a session the running stream on C1 is shut down and the receiver app is restarting.
Is there a way to join an active session? Or is that a job which has to be done by the web app running on the Chromecast device?
EDIT:
my sender app is a native Android app
Thanks!
You should have a look to the TicTacToe application. I think it does exactly that where 2 players can join the same game :
https://github.com/googlecast/cast-android-tictactoe
Hope this helps.
JN
What sort of sender are you using? Is it a native app (i.e. using Android or iOs SDK on a mobile device) or the sender is a chrome app?
On the receiver, you create a Receiver object and a ChannelHandler. You use the receiver to generate a ChannelFactory which you then pass to the ChannelHandler. The ChannelHandler now handles the creation of channels on the receiver. You will want to add an EventListener to the handler to listen to messages. Based on those messages you can do various things.
receiver = new cast.receiver.Receiver(YOUR_APP_ID, [YOUR_PROTOCOL], "", 5);
var dashHandler = new cast.receiver.ChannelHandler(YOUR_PROTOCOL);
dashHandler.addChannelFactory(receiver.createChannelFactory(YOUR_PROTOCOL));
dashHandler.addEventListener(cast.receiver.Channel.EventType.MESSAGE, onMessage.bind(this));
receiver.start();
...
onMessage = function (e) {
var message = e.message;
switch (message.type) {
...
}
}
On the sender, after a session is created you will want to send a check status message to the receiver to see if there are already channels attached. You can do this via your MessageStream and your receiver needs to respond in such a way that the MessageStream gets its status updated. You check that status to see if there are channels. If there are you can start listening to updates for your receiver. If not you can send a load event to the receiver to start your activity.
MediaProtocolCommand cmd = mMessageStream.requestStatus();
cmd.setListener(new MediaProtocolCommand.Listener() {
#Override
public void onCompleted(MediaProtocolCommand mPCommand) {
if (mMessageStream.getState() == 'channelsExist') {
//Start New Activity
} else {
//Join Existing Activity
}
#Override
public void onCancelled(MediaProtocolCommand mPCommand) {
}
});
This is kind of a vague response, but it could be more specific if I knew what you were trying to do. My app is using Google's RAMP protocol to play videos so my MessageStream and all it's messages are already defined. If you're doing something different, you need to create your own MessageStream.
Sorry for the late answer, but I figured it out by myself: It wasn't such complicated at all
I started the an Application like this
try {
mSession.startSession(applicationName,applicationArgs);
} catch (IllegalStateException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
} catch (IOException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
}
But it seems, that the MimeData applicationArgs is not needed at all. By removing the arguments and starting the session like below it works really fine!
try {
mSession.startSession(applicationName);
} catch (IllegalStateException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
} catch (IOException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
}
I hope this works for you too!