I am trying to utilize ChromeCustomTabs into our project. I ran into several issue when I used mayLaunchUrl. I checked the code Google has on the github. I simply set up an button to test the mayLaunchURL (prerender feature), when I looked up the traffic using chrome dev tool. I did the the traffic and tab got trigger and the url got loaded ( it is simply a GET call with params). However, when I click it multiple times, (after 8-10times, with different params everytime), it STOP working. I stop seeing the requests sent out. (Not seen on chrome dev tool, nor the Proxy I set up).
I wonder if there is a limit times ( restriction) for mayLaunchURL feature, in other words, how many pages we can pre-render in this case? Is there a way to manually cancel the pre-render page and free the resource?
is there a restriction in terms of times to bindCustomTabsService? The way I did to call mayLaunchURL is to have an activity and kill the activity once I finish the tab. Can I bind the service each time even I “kill (finish)” the activtiy every time?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
customTabActivityHelper = new CustomTabActivityHelper();
customTabActivityHelper.setConnectionCallback(this);
}
#Override
protected void onStart() {
super.onStart();
customTabActivityHelper.bindCustomTabsService(this);
}
#Override
public void onCustomTabsConnected() {
Boolean mayLaunchUrlAccepted = customTabActivityHelper.mayLaunchUrl(Uri.parse(“the URL?f=“+params), null, null);
// the mayLaunchUrlAccepted always return true in my case. Even when there is no request sent.
}
Yes, mayLaunchURL() are very expensive in terms of battery/RAM/network, so it is throttled on app UID level. But limits get dropped after some time.
Best strategy is to use mayLaunchURL() if the confidence that the user will navigate to the URL is very high.
There is the "low confidence" mayLaunchURL() which is not throttled, but performs a more limited set of actions (currently preconnect, not specified which, may change). The low confidence mayLaunchURL is triggered by providing null as the uri and a list of URLs in otherLikelyBundles.
Related
For the past few days i've been trying to show the online/offline status of a user.. For this i have a register activity where they register and their info gets saved in firebase and if they exit an activity i have overriden its onstop method and made the value to set to offline... but if the user suddenly loses internet connection it still shows online.. i cant change it to offline because internet is needed to make a change in the database and the use doesn't have internet... SO how do i set the database value to offline... i googled quite some stuff about this but didnt find anything... Can anyone please help me out please
My code
#Override
protected void onStart() {
super.onStart();
fetchData();
// mDatabaseReference.child("UserData").child(UID).child("Online").setValue("True");
}
#Override
protected void onStop() {
super.onStop();
fetchData();
// mDatabaseReference.child("UserData").child(UID).child("Online").setValue(false);
}
What you're trying to do is known as a presence system. The Firebase Database has a special API to allow this: onDisconnect(). When you attach a handler to onDisconnect(), the write operation you specify will be executed on the server when that server detects that the client has disconnected.
From the documentation on managing presence:
Here is a simple example of writing data upon disconnection by using the onDisconnect primitive:
DatabaseRef presenceRef = FirebaseDatabase.getInstance().getReference("disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnect().setValue("I disconnected!");
In your case this could be as simple as:
protected void onStart() {
super.onStart();
fetchData();
DatabaseReference onlineRef = mDatabaseReference.child("UserData").child(UID).child("Online");
onlineRef.setValue("True");
onlineRef.onDisconnect().setValue("False");
}
Note that this will work in simple cases, but will start to have problems for example when your connection toggles rapidly. In that case it may take the server longer to detect that the client disappears (since this may depends on the socket timing out) than it takes the client to reconnect, resulting in an invalid False.
To handle these situations better, check out the sample presence system in the documentation, which has more elaborate handling of edge cases.
After reading the documentation on Spotify's Android Media Notifications API, https://beta.developer.spotify.com/documentation/android-sdk/guides/android-media-notifications/, I successfully managed to receive the notifications metadata and it is displayed properly on my app.
However, the notifications metadata is only updated when the queue changes, when the track changes, and when playback is changed, so unless one of these three actions happens, the "positionInMs" intent extra isn't sent.
As of right now as a workaround I am simply starting a timer using the time the intent was sent, the last known playback position, and the track duration to track current playback position.
This seemed to work at first, but after further testing I've realized that the timer I set can go out of sync, if the track the user is listening to freezes because of a slow internet connection.
Any ideas to properly track the playback position, while accounting for a slow internet connection? Or are there any alternatives I should look into?
I understand that this question is rather old, but I am going to answer anyway if anyone else comes across it.
I recommend constantly querying Spotify to get the playback position. One way you can do this is by using a timer and querying Spotify every given time frame. The below example queries Spotify every 100ms. If you want to reduce/increase the numbers of queries, you can simply use stopwatch.setClockDelay() and provide your required time
For instance, you can use this timer library
implementation 'com.yashovardhan99.timeit:timeit:1.2.0'
Then use the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spotify);
Stopwatch stopwatch = new Stopwatch();
stopwatch.setOnTickListener(this);
stopwatch.start();
}
#Override
public void onTick(Stopwatch stopwatch) {
Data.getAndroidSpotifyAppRemote().getPlayerApi().getPlayerState().setResultCallback(new CallResult.ResultCallback<PlayerState>() {
#Override
public void onResult(PlayerState playerState) {
Log.d("TAG", playerState.playbackPosition);
}
});
}
Don't forget to add the following code at the top of your class:
implements Stopwatch.OnTickListener
I use Google Play Games Services and everythink working fine (leaderboards, random opponent etc etc)
But when a player call finishMatch(), the status of match.canRematch() is always "true", beyond the result.
If the player has won the battle may not be able to ask for a rematch!
I use this code to send the result:
Games.TurnBasedMultiplayer.finishMatch(mGoogleApiClient,
mMatch.getMatchId(), mMatch.getData(), myscore, creatorscore).setResultCallback(
new ResultCallback<TurnBasedMultiplayer.UpdateMatchResult>() {
#Override
public void onResult(
TurnBasedMultiplayer.UpdateMatchResult result) {
processResult(result);
}
});
I would like to disable the possibility of revenge. How can I do?
Ok. This IS an answer.
It is not possible from the API to disallow rematch.
However, I just discovered a workaround that achieves the same effect.
detect whether a match is a rematch by calling getMatchNumber() and getPreviousMatchData(). Cancel/Dismiss the match if the former isn't 1 or the latter isn't null. It ensures a rematch user input will have the same effect as a dismissal.
when a match is completed completely (cancelled, expired, or MATCH_STATUS_COMPLETE && MATCH_TURN_STATUS_COMPLETE), dismiss it right away. It minimizes the chance that the user will even see the "Match complete, rematch" UI. This check can also be checked periodically for matches in the inbox.
I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.
What is the most precise way to measure startup time of an Android app?
By startup time I mean the difference between 2. and 3. :
The app process is not running
User clicks on app icon in the launcher
Main Activity is fully initialized
So I basically need to somehow get time elapsed since JVM started and log it.
I understand I am too late to answer, nonetheless, this precisely answers the question.
This information gets logged on Logcat by default for API version 19 or higher.
From Android 4.4 (API level 19), logcat includes an output line containing a value called Displayed. This value represents the amount of time elapsed between launching the process and finishing drawing the corresponding activity on the screen.
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
The key is looking for it in the right place -
If you’re tracking logcat output from the command line, or in a terminal, finding the elapsed time is straightforward. To find elapsed time in Android Studio, you must disable filters in your logcat view. Disabling the filters is necessary because the system server, not the app itself, serves this log.
The extracts are from the documentation.
I'm going to interpret your question as 'Is my app startup time fast enough. How can I check I have done everything I can do?'
The startup time is largely a false metric as it will vary across devices and ROMs. I guess what you're most likely to be interested in is how much of your code is taking a long time to execute and what is potentially blocking the main thread.
I've found the most effective way of doing this is to use Traceview on the app start and then reviewing how long it takes the method to execute and if there are any gaps on the main thread.
Start tracing:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing("startup");
}
}
Stop tracing:
#Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Debug.stopMethodTracing();
}
Once the trace has been collected, you should be able to see anything that is having a major impact on startup time. In my case, seen below, there was a big gap on the UI thread where is was being blocked.
It transpired that both Crashlytics and Coremetrics were requiring a call to randomUUID() which was then being synchronized across threads and blocking the main thread. The solution was just to spin up a new thread to initialise the Coremetrics code.
This is something I would not have otherwise picked up with just measuring the startup time, but it actually sped up the app 'startup time' by a few hundred milliseconds.
Here's another snapshot after spinning off a separate thread for Coremetrics initialisation:
Check in adb shell in below manner.
adb shell
adb logcat -b events | grep am_activity_launch_time
[Output]
01-01 12:32:53.469 1236 1262 I am_activity_launch_time:
[0,205360373,com.sec.android.app.clockpackage/.ClockPackage,378,**378**,0]
Remarks:
Launch time for Clock is 378ms.
Wrap the entire onCreate() method in a TimingLogger. Just put this at the beginning:
TimingLogger timings = new TimingLogger(TAG, "methodA");
and this at the end:
timings.dumpToLog();
If you want to drop times at some intermediate step, you can do timings.addSplit("name"); to get the time it took to get to that step.
A simple way to display startup time in android.
Sometimes the Displayed line in the logcat output contains an additional field for total time. For example:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
In this case, the first time measurement is only for the activity that was first drawn
Source: Time to initial display
It is possible to implement time tracking using the next code:
Override your Application:
public class CustomApplication extends Application {
public final static long APP_START_TIME = System.currentTimeMillis();
/**
* Do all other application stuff
*/
}
And add few rows to your main Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View contentView = findViewById(android.R.id.content);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
contentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
contentView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
long launchTime = System.currentTimeMillis() - CustomApplication.APP_START_TIME;
Log.e("TEST", "App launch time = " + launchTime);
}
});
}
}
And don't forget to define your custom application in Manifest:
<application
android:label="#string/app_name"
android:name=".CustomApplication" >
</application>
Important: You have to kill your application before launch, because Application stores static variable which tracks initial time.
Use SysTrace
Also the Trace class can be used to measure sections using
Trace.beginSection("name");
Trace.endSection();
This YouTube video is a quick primer as well.
I think this has been built into Firebase Console, under performance now
One possibility would be is to save the time at the beginning of the onCreate() method and at the end of the onCreate() method and then subtract those times from each other to get the time taken to initialize the app.