Why views are not updated on runnable in android widget? - java

I am trying to make one of the views in android widget visible for a second, but so far no success. Can someone point me in the right direction, please?
I've tried to do it with animation, timer but so far I got the nearest with runnable. Well, kind of as I get System.out.println("run test") executed but views are not updated.
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (MinutesClicked.equals(intent.getAction())){
//your onClick action is here
///////////////////////////////////////////////////////////
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final RemoteViews views;
ComponentName appWidget;
views = new RemoteViews(context.getPackageName(), R.layout.nixie_clock);
appWidget = new ComponentName(context, NixieClock.class);
final Runnable r = new Runnable() {
public void run() {
views.setViewVisibility(R.id.textDateDay, VISIBLE);
System.out.println("run test");
}
};
handler.postDelayed(r, 1000);
/////////////////////////////////////////////////////////
appWidgetManager.updateAppWidget(appWidget, views);
}
}
So far I am getting System.out.println("run test") printed but expected views are not made VISIBLE. I can make the view visible after a click but I cannot make it appear only for a second and disappear. Thank you in advance for any help.

You are updating the RemoteViews, but you are not sending the updated RemoteViews anywhere. You need to call updateAppWidget() again after updating the RemoteViews.
Note that your process might be terminated before the one-second delay elapses, in which case your view will not become visible.

Related

Android studio check if Mediaplayer is playing in a screen widget activity

There'd be a button on the home screen which would play a certain song and change the background image of the button. If the user clicks on the button again (when the music is playing) then the music should stop and the background image of the button should set itself back to the general position. But it looks like the program can't detect if my Mediaplayer is playing. What am I missing here?
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
AppWidgetManager appWidgetManager= AppWidgetManager.getInstance(context);
RemoteViews rv= new RemoteViews(context.getPackageName(),
R.layout.playbtn_widget);
if (intent.getAction().equals("btnPlay")) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer= MediaPlayer.create(context,R.raw.itsmylife);
mediaPlayer.start();
rv.setImageViewResource(R.id.imbtnwidget,
R.drawable.btnk32);
} else {
mediaPlayer.stop();
}
mediaPlayer.setOnCompletionListener(mediaPlayer -> {
rv.setImageViewResource(R.id.imbtnwidget,
R.drawable.btnk3);
appWidgetManager.updateAppWidget(new ComponentName(context,
BtnAppWidgetProvider.class), rv);
});
appWidgetManager.updateAppWidget(new ComponentName(context,
BtnAppWidgetProvider.class), rv);
}
}
It should set the background image back and stop the music when I tap on the button, but it just starts the mediaplayer again and the background image remains the same. I have no idea how I could fix this. It seems like it creates a new mediaplayer every single time
Issue
It creates a new Media Player because the class is recreated or re-executed. This clears all the variables and re-defines them. This makes the issue in your case.
Solution
Just create a class name anything like MediaPlayerHelper.java
Create a variable of MediaPlayer which is public and static. Like this:
public static MediaPlayer mp;
Now, when the button is pressed, you can check if it is playing or not. Something like this:
if(MediaPlayerHelper.mp != null && MediaPlayerHelper.mp.isPlaying()){
// the media player is currently playing. Stop it.
}else{
// the media is not playing. Start it
}

Inconsistent results with startAnimation in Android Studio

I'm trying to animate my imagebuttons by making them wobble when clicked.
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.buttonStart:
buttonStart.startAnimation(wobble);
Intent i;
i = new Intent(this, CityRendActivity.class);
startActivity(i);
break;
}
}
When I click my Start button, it very slowly starts to wobble, but only appears to shake back and forth like 3 times, and a lot slower than I have defined in the xml file. When I remove the lines that contain the intent code, the wobble works perfectly and the button shakes 5 times quickly (though now of course it doesn't load up my other activity).
So why would the code after the wobble animation effect how it's run? Doesn't each line get resolved individually before proceeding? I don't understand how loading up a different activity would effect the animation that I've set up. Any thoughts? Thanks.
Try adding animation listener for your animation and onAnimationEnd() start your Activity Intent.
wobble.setAnimationListener(new AnimationListener(){
#Override
public void onAnimationStart(Animation animation){}
#Override
public void onAnimationRepeat(Animation animation){}
#Override
public void onAnimationEnd(Animation animation){
startActivity(new Intent(YourCurrentActivity.this, CityRendActivity.class)); // if the code is in Fragment, then replace YourCurrentActivity.this by getActivity()
}
});
Actually In this code. animation and starting a new activity will execute at a same time. that will disturb the animation in between. so delay the starting of activity with your animation time. so that animation will completed and then your Activity will start.hope this work for you.
new Handler().postDelayed(new Runnable(){
#Overide
void run(){
startActivity(new Intent(this, CityRendActivity.class));
}
},time_ofanimation);

runOnUiThread inside a widget

I want to make an HTTP Request inside the app widget I've built.
The idea is that every couple of hours the widget will update itself by making an HTTP Request and use the information of it to update its views.
I've already tried to use a Thread in onUpdate function, the HTTP Request is working just fine, the problem is that I can't use runOnUiThread() to update the views, because I have no parent activity to run this function on.
Is there another way to update the widget's views inside the Thread?
Sample code:
public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
final int appWidgetId = appWidgetIds[i];
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_card);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Http.Response resp = Http.postData("http://www.example.com", null, null, null);
views.setTextViewText(R.id.textview, resp.body);
}
catch (Exception ex) {
Log.e(TAG, Log.getStackTraceString(ex));
}
}
}
}
Thank you upfront.
I've already tried to use a Thread in onUpdate function
That is not a very good idea. Your process can be terminated before your work completes. Instead, create an IntentService that does the network I/O and updates the app widget via an AppWidgetManager.
the problem is that I can't use runOnUiThread() to update the views, because I have no parent activity to run this function on
Since you do not have any views to update, you do not need to worry about this. You can set up the RemoteViews and hand them to the AppWidgetManager on a background thread.

runOnUiThread method analog for widget?

I have a widget which needs to do some operations in another thread. It has a method which processes some data and shows the result in a TextView on the widget.
To implement this, I need to call my method in a separate thread. Then I need to include some code to the end of that method to show the results on the widget (something like textView1.setText("my results");. This has to be done in a UI thread. I want to use the method runOnUiThread. But it exists only for an activity. Is there an analog of this method for widget class? What can I do to use that method in my widget?
Here is my code:
public class MyWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
{
//...
//here I need to launch a method toBeLaunchedInASeparateThread in a separate thread
}
public void toBeLaunchedInASeparateThread()
{
// ... many operations
int result = 0;
//here I need to launch the following line in the UI thread to follow Android guidelines
setTextToTextView(context, "My result is " + result);
}
public static void setTextToTextView(Context context, String text)
{
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_sample);
views.setTextViewText(R.id.widgetTextViewCard, text);
ComponentName myWidget = new ComponentName(context, MyWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(manager.getAppWidgetIds(myWidget), views);
}
}
you can use an Handler, to connect with the UI Thread and post on its queue. Handler.post(Runnable). Here the documentation
blackbelt's answer is great, however you can also use textView1.post(runnable) and methods like that. This way you don't have to create a Handler instance, and the code will run on UI thread. AFAIK both solution will do the exactly same things.
For RemoteViews:
Handler mHandler = new Handler();//this must be ran on the UI thread.
....
mHandler.post(new Runnable(){
public void run() {
toBeLaunchedInASeparateThread();
}
});

How can i pause executing code until animation finishes

public void startGameButtonClicked(View view) {
final TextView shadow = (TextView) findViewById(R.id.main_menu_start_game_button_shadow);
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.main_menu);
shadow.startAnimation(animation);
/** Ugly prototype pausing */
final long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < 600) {
Log.i("test", Boolean.toString(animation.hasEnded()));
}
final Intent intent = new Intent();
intent.putExtra(EXTRA_BUTTON_ID, START_GAME_BUTTON);
setResult(RESULT_OK, intent);
finish();
}
My animation has duration = 400, how can i pause everything except animation after calling shadow.startAnimation(animation); ?
I asking becouse, as you can see - animation is set for button click action, which kills current activity, so animation isnt shown completely.
You must define "pause everything" to get an answer for it.
What I'll propose is to implement AnimationListener in your Activity, and point it to the Animation. Then in onAnimationEnd() simply call finish().

Categories

Resources