Animated Vector drawable animation not working properly - java

I want to run AnimatedVectorDrawable animation on infinite loop.
final AnimatedVectorDrawableCompat avd = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_anim_happy);
mImageView.setImageDrawable(avd);
// animation on infinite loop
avd.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
#Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
Log.e(TAG, "onAnimationStart() called");
}
#Override
public void onAnimationEnd(Drawable drawable) {
Log.e(TAG, "onAnimationEnd() called");
avd.start();
}
});
avd.start();
}
This works fine when I tested with Nougat device. But when I try to run this on KitKat device, callback is called but animation is not started again. There is no
"onAnimationStart() called" log message. But upon doing the following.
#Override
public void onAnimationEnd(Drawable drawable) {
Log.e(TAG, "onAnimationEnd() called");
if (avd.isRunning()) {
Log.e(TAG, "avd running!!");
avd.stop();
}
avd.start();
}
onAnimationEnd() and onAnimationStart() are getting called again and again. But for some reason animation just stopped after playing for one time.

I was having the same issue with old platforms, turns out i work around it by posting the start after the end event.
imageView.post(new Runnable() {
#Override
public void run() {
avd.start();
}
});

Related

Android: How to use CountDownLatch?

I have a function that requests data from an api and fills an array list.
Then i use the data from the arraylist in a textView. The problem that occurs is that the function takes time to load the data and the code in which i set the text view gets executed before the arraylist is populated resulting in a crash...I have used Countdown latch to tackle this problem but it isnt working
i have used it wrong most probably.
apirequest function
private void RequestDataFromApi() {
DotaAPIEndpoints textApiService= API_Client.getClient().create(DotaAPIEndpoints.class);
Call<List<Heroes>> call2 =textApiService.getHeroes();
call2.enqueue(new Callback<List<Heroes>>() {
#Override
public void onResponse(Call<List<Heroes>> call, Response<List<Heroes>> response) {
hero_list.clear();
hero_list.addAll(response.body());
}
#Override
public void onFailure(Call<List<Heroes>> call, Throwable t) {
Toast.makeText(MainActivity.this, "hero_list call failed!", Toast.LENGTH_SHORT).show();
}
});
requestLatch.countDown();
}
setText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
requestLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
textt.setText(hero_list.get(0).getHeroImg());
}
});
setText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
requestLatch.await();
You cannot call await on the UI thread. Calling await at this point in the above code is telling the UI thread to wait - if the UI thread is waiting, it cannot draw the screen updates, so the system will crash with an Activity Not Responding error.
Perhaps this helps, this is a way to safely allow the button to be clicked and not crash if the data has not loaded yet. (No need for a CountdownLatch at all)
setText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(hero_list.isEmpty()) {
Toast.makeText(MainActivity.this, "List not ready", Toast.LENGTH_SHORT).show();
return;
}
textt.setText(hero_list.get(0).getHeroImg());
}
});

Android camera works for one time only after giving permission

I try to show the content of the built-in camera inside my android device using ArCore. I have handled a code for asking permission at the beginning of the application. If I provide the permission I can see the current image stream coming from the camera.
After relaunching the application the result is black. The only solution is to revoke the camera permission inside the setting. Then the application asks again for permission and shows the image stream on the screen.
Is anybody who face the same problem? Do I have to refresh the permission? If I do RequestCameraPermission(); without checking permission, the activity is paused and resumed in a cycle. But I can see the first frame.
In the console the following error appears:
D/ACameraDevice: Device error received, code 3, frame number 51, request ID 0, subseq ID 0
and android_camera.cc:1088 Camera capture failed! frame: 51 reason: 1.
Code 3 is ERROR_CAMERA_DISABLED depending on https://github.com/aosp-mirror/platform_development/blob/master/ndk/platforms/android-24/include/camera/NdkCameraDevice.h
After some time only
I/native: analytics_logger.cc:190 The AnalyticsClient.sendAnalyticsMessage() method returned false. Will retry...
E/native: analytics_logger.cc:198 Could not send event. Event will be dropped.
is called in a loop. There is no activity anymore.
My code:
public class GameActivity extends NativeActivity
{
static GameActivity s_Instance;
public static GameActivity GetInstance()
{
return s_Instance;
}
#Override
public void onCreate(Bundle _SavedInstanceState)
{
super.onCreate(_SavedInstanceState);
s_Instance = this;
nativeInitializeInterface(getApplicationContext());
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume()
{
super.onResume();
if (!HasCameraPermission())
{
RequestCameraPermission();
return;
}
RequestCameraPermission();
}
#Override
protected void onPause()
{
super.onPause();
}
#Override
public void onStop()
{
super.onStop();
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public void onRequestPermissionsResult(int _RequestCode, String[] _Permissions, int[] _Results)
{
if (!HasCameraPermission())
{
Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG).show();
if (!ShouldShowRequestPermissionRationale())
{
// Permission denied with checking "Do not ask again".
LaunchPermissionSettings();
}
finish();
}
}
public int GetDeviceOrientation()
{
return getResources().getConfiguration().orientation;
}
public int GetDeviceRotation()
{
return getWindowManager().getDefaultDisplay().getRotation();
}
public int GetDeviceDimensionWidth()
{
Point Size = new Point();
getWindowManager().getDefaultDisplay().getSize(Size);
return Size.x;
}
public int GetDeviceDimensionHeight()
{
Point Size = new Point();
getWindowManager().getDefaultDisplay().getSize(Size);
return Size.y;
}
public boolean HasCameraPermission()
{
return this.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
public void RequestCameraPermission()
{
this.requestPermissions(new String[] {Manifest.permission.CAMERA}, 0);
}
public boolean ShouldShowRequestPermissionRationale()
{
return this.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA);
}
public void LaunchPermissionSettings()
{
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", this.getPackageName(), null));
this.startActivity(intent);
}
public native void nativeInitializeInterface(Context context);
static
{
System.loadLibrary("app_droid");
}
}
Where exactly do you have the logic for presenting the image on screen? Maybe you only have it inside the permission granted callback.
(I'd put this answer as a comment, but can't yet due to reputation)

Google Glass Immersion - OnClick not working inside a separate thread

My problem is pretty simple. I am creating a card based on the result of a HTTP query performed inside a separate thread. The card also has an onclick method and is defined inside a runOnUiThread() located inside the separate thread. However, when the device is tapped, the onclick event isn't fired.
Here is my code:
private void login() {
Runnable r = new Runnable() {
#Override
public void run() {
// irrelevant code
runOnUiThread(new Runnable() {
#Override
public void run() {
setContentView(buildError(code));
}
}
}
Thread t = new Thread(r);
t.start();
}
private View buildError(String code) {
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.ALERT);
card.setIcon(R.drawable.ic_warning_150);
if (code.equals("1"))
card.setText("Incorrect credientals");
else
card.setText("Unexpected error");
card.setFootnote("Tap to try again");
View cView = card.getView();
cView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("Event", "Clicked"); // This is what isn't triggering
}
});
cView.setFocusable(true);
cView.setFocusableInTouchMode(true);
return cView;
}
Even though the snippet of code contains an error (can't be compiled, missing ; at the Runnable statement), you were on the right track.
The View simply needs to request the focus in order to be clickable right away. Otherwise you'll have to move the focus manually.
cView.setFocusable(true);
cView.setFocusableInTouchMode(true);
cView.requestFocus();
Reference

Is there such a thing as too many chromecast devices on one network?

I have an app that uses the CastCompanionLibrary and I'm having a weird issue. On a small network with one chromecast device my application is able to detect it and show the MediaRouterItem.
Although, I had a beta tester say that they were not able to get any of their devices detected, so the icon never shows up for them. Come to find out they are connected to a larger, shared network with multiple chromecast devices connected to it. They said that they are able to detect all of the chromecast devices with other apps such as YouTube and Localcast though. Which is weird because that leads me to believe that maybe I'm not doing something right with the discovery process.
Unfortunately, I am not in a position where I can have a network with multiple chromecast devices to debug this issue, so I was just wondering if anyone else had a similar issue? Or is there a certain method that you have to call with the CastCompanionLibrary that I'm missing?
EDIT
I am using the APP_ID that has been published, so I know that it isn't a whitelisting issue.
The code I use for discovery is completed by the CastCompanionLibrary. This is what I use once the onCastDeviceDetected() callback is called:
mCastConsumer = new VideoCastConsumerImpl() {
#Override
public void onFailed(int resourceId, int statusCode) {
}
#Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "onConnectionSuspended() was called with cause: " + cause);
}
#Override
public void onConnectivityRecovered() {
}
#Override
public void onCastDeviceDetected(final MediaRouter.RouteInfo info) {
if (!MyApplication.isFtuShown(Home.this)) {
MyApplication.setFtuShown(Home.this);
Log.d(TAG, "Route is visible: " + info);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (mediaRouteMenuItem.isVisible()) {
Log.d(TAG, "Cast Icon is visible: " + info.getName());
//showFtu();
}
}
}, 1000);
}
}
};
MyApplication.class:
public static boolean isFtuShown(Context ctx) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(ctx);
return sharedPref.getBoolean(FTU_SHOWN_KEY, false);
}
public static void setFtuShown(Context ctx) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(ctx);
sharedPref.edit().putBoolean(FTU_SHOWN_KEY, true).commit();
}

Unexpected behavior: immediate completion of media player

I am trying to restore audio to the position it was and the file it was when the user left the fragment. To do this I save the location of the audio file, and the seek position using personal prefs, along with a boolean for whether or not the audio was playing when the user left. I save this info first thing in onPause().
When I resume, I initialize the views etc. and the very last thing I do in onResume is read from personal prefs and play the audio stored there is appropriate.
However when I try to play from onResume, the media completion listener gets called immediately and the file gets skipped.
I have been running tests and I know that the media player is handed the right data, is prepared correctly and set to play.
The way I am trying to play the audio is the same way I do it if a user clicks manually to play audio, and that works flawlessly.
Only when trying to 'restore' the audio to where it was when a user left does the completion listener get called immediately.
Has anyone seen this before?
public void setAudioURLAndPLay(Context context, String url)
{
Log.d(TAG, "setAudioURLAndPLay");
CacheQueue.getInstance().addImmediateTaskToQueue(CacheQueue.AUDIO_TASK, context, url, 0, handler);
}
private void playCahcedFile(String location)
{
Log.d(TAG, "playCahcedFile");
try
{
this.reset();
this.setAudioStreamType(AudioManager.STREAM_MUSIC);
this.setDataSource(location);
this.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
setPlay();
}
});
this.prepareAsync();
}
catch (Exception e)
{
Log.d(TAG, "Exception", e);
}
}
public void setPlay()
{
Log.d(TAG, "setPlay");
this.start();
this.setProgressHandler(this.listener);
}
and where the calls are being made
public void initializeFromResume()
{
PersonalPrefs prefs = new PersonalPrefs(getActivity());
if (!prefs.isPLaying())
{
return;
}
else
{
playNewAudio(prefs.getURL());
// ((ActivityMain) getActivity()).getMediaManager().setSeek(prefs.getSeek());
}
}
private void playNewAudio(String url)
{
getMediaManager().setAudioURLAndPLay(getActivity(), url)
mediaState = MediaState.playing;
initializeSeekBar();
getMediaManager().setOnCompletionListener(this);
mediaController.togglePlayButton(mediaState);
}
I figured it out and will post the answer to anyone who has similar troubles in the future.
Just need to run a post delayed. Not exactly amazing, but it works.
h.postDelayed(new Runnable()
{
#Override
public void run()
{
PersonalPrefs prefs = new PersonalPrefs(getActivity());
playNewAudio(prefs.getURL());
}
}, 1000);

Categories