1

I tried to implement a timer in Android and while it times it doesn't exactly work as expected.

I have the following code for when the timer expires (located in it's own method):

Button b = (Button) this.findViewById(R.id.actionButton);
        if(b != null && (!b.isEnabled() || b.getText().toString() == "Loading.."))
        {
            Toast.makeText(this, "Ad failed. Loading next ad...", Toast.LENGTH_SHORT).show();
            SetupNextAdd(true); // The ad failed
        }

The button is a button that simply shows an ad so the user can gain a reward. Simple right?

The button is enabled when the ad is finished loading in the background so that there's something ready for the user when they click.

The timer is to double check the ad has loaded. If the ad has failed I'll know because the button will still be disabled and or the text will still be loading.

If the button is enabled I want the timer to finish its course and be free.

I thought this would be simple. Create a nice timer. Check the button and if needed, reload the ad. Done.

But the issue is that the button returned still says the text is loading and it's disabled. I know the button isn't really though as I can see the button on the screen is neither disabled nor has it's text as loading. So why is find by id returning a button that's disabled? It's like it's returning an old ver of the button before it was changed.

This also causes an infinite loop as the buttons state returned never matches the screens button state.

So how can I get a timer to work the way I expect? And why would it be returning the old button?

Here is a complete example showing the problem.

View:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/actionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="350dp"
        android:background="@android:color/holo_blue_bright"
        android:onClick="ShowAdd"
        android:padding="5dp"
        android:text="Loading..."
        android:enabled="false"/>
    <RelativeLayout
        xmlns:ads="http://schemas.android.com/apk/res-auto"
        android:layout_height="wrap_content"
        android:layout_width="match_parent">

        <com.google.android.gms.ads.AdView
            android:id="@+id/adView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            ads:adSize="BANNER"
            ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
        </com.google.android.gms.ads.AdView>
    </RelativeLayout>

</LinearLayout>

Java code:

public class MainActivity extends AppCompatActivity {

    private InterstitialAd mInterstitialAd;
    private RewardedVideoAd mAd;
    private AdView mAdView;
    private CountDownTimer timer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        timer = new CountDownTimer(15000, 5000) {
            @Override
            public void onTick(long l) {

            }

            @Override
            public void onFinish() {
                TimerDone();
            }
        };

        SetupNextAdd();
        ShowBannerAd();
    }

    public void TimerDone()
    {
        Button b = (Button) findViewById(R.id.actionButton);
        if(b != null && (!b.isEnabled() || b.getText().toString() == "Loading.."))
        {
            Toast.makeText(this, "Ad failed. Loading next ad...", Toast.LENGTH_SHORT).show();
            SetupNextAdd(); // The ad failed
        }
    }

    public void EnableDisableButton(String action)
    {
        MainActivity a = this;
        Button b = (Button)a.findViewById(R.id.actionButton);
        if(action == "enable")
        {
            b.setEnabled(true);
            b.setText("View Ad");
            timer.cancel();
        }
        else
        {
            b.setEnabled(false);
            b.setText("Loading..");
        }
    }
    public void ShowAdd(View view)
    {
        if(mAd.isLoaded()) {
            mAd.show();
        }
    }

    private void SetupNextAdd()
    {
        timer.cancel();
        timer.start();

        if(mAd == null) {
            buildReward();
        }
        requestNewReward();

    }
    private void buildReward()
    {
        mAd = MobileAds.getRewardedVideoAdInstance(this);
        mAd.setRewardedVideoAdListener(new RewardedVideoAdListener() {
            @Override
            public void onRewardedVideoAdLoaded() {
                EnableDisableButton("enable");
            }

            @Override
            public void onRewardedVideoAdOpened() {

            }

            @Override
            public void onRewardedVideoStarted() {

            }


            @Override
            public void onRewardedVideoAdClosed() {
                EnableDisableButton("disable"); // disable till loaded. No reward for you
            }

            @Override
            public void onRewarded(RewardItem rewardItem) {
                EnableDisableButton("disable");
            }

            @Override
            public void onRewardedVideoAdLeftApplication() {

            }


            @Override
            public void onRewardedVideoAdFailedToLoad(int i) {
                Toast.makeText(getApplicationContext(), "ad failed. Try again.", Toast.LENGTH_SHORT).show();
                EnableDisableButton("disable");
                SetupNextAdd();
            }
        });
    }

    private void requestNewReward()
    {
        mAd.loadAd("ca-app-pub-3940256099942544/5224354917", new AdRequest.Builder().build());
    }

    private void ShowBannerAd()
    {
        mAdView = (AdView) findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);
    }
}
Jeremy Styers
  • 497
  • 5
  • 23
  • 1
    I recommend that you provide a [mcve]. In particular, show where and how you are executing the above code, including how you are setting up and using your timer. – CommonsWare Apr 09 '17 at 22:28
  • I have updated to include a very simple example. Using the above will generate an infinite loop in the timers done method – Jeremy Styers Apr 09 '17 at 23:29
  • Also I noticed the timer isn't canceling. Even when the cancel method is called the timer still runs till completion. Obviously I want the timer to stop if the enable went through. But the enable goes through fine and the text changes but the timer doesn't cancle. – Jeremy Styers Apr 10 '17 at 01:46

0 Answers0