【问题标题】:Extending Activity to implement an Idle timer扩展 Activity 以实现空闲计时器
【发布时间】:2011-04-29 08:43:23
【问题描述】:

我开发了一些实现计时器的代码 - 它每秒滴答一次,并且在 x 秒不触摸显示屏后启动“空闲”活动。 但是,这需要为大约 8 个活动实现...我可以将相关代码复制并粘贴到每个活动,但这不是一个优雅的解决方案。

所以,我开始创建自定义活动“TimedActivity”来扩展 Activity。然后我需要实现的其他活动可以实现“TimedActivity”。

但是,我的 TimedActivity 如何检测 onTouch 事件?

这是我目前所拥有的:

public class TimedActivity extends Activity implements OnTouchListener
{
    private LinearLayout mLinearLayoutMain;//intended to be the root node in the XML
    private Timer mTimerSeconds;
    private int mIntIdleSeconds;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        //NO setContentView() 

        mIntIdleSeconds=0;

        mTimerSeconds = new Timer();
        mTimerSeconds.schedule(new TimerTask()
        {
            @Override
            public void run()
            {
                timerSecondsCounter();
            }
        }, 0, 1000);

        //the whole screen should become sensitive to touch
        //HOWEVER, there's no View established
        mLinearLayoutMain = (LinearLayout) findViewById(R.id.layout_main);
        //mLinearLayoutMain remains null, so next line excepts
        mLinearLayoutMain.setOnTouchListener(this);
    }


    @Override
    protected void onDestroy()
    {
        if (mTimerSeconds != null)
        {
            mTimerSeconds.cancel();
        }
        super.onDestroy();
    }


    public boolean onTouch(View v, MotionEvent event)
    {
        mIntIdleSeconds=0;
        return false;//do not consume
    }

    private void timerSecondsCounter()
    {
        mIntIdleSeconds++;

        if (mIntIdleSeconds == Constants.MAX_IDLE_TIME_SECONDS)
        {
            final Intent intent = new Intent(this, what.ever.com.Idle.class);
            startActivity(intent);
        }
    }
}

使用 this 的后续活动将使用:

public class ActivitySelect extends TimedActivity
{
}

视图的 xml 将是:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/layout_main">

<!-- MORE STUFF --->

</LinearLayout>

我觉得我已经很接近了,但是我需要做些什么才能让它发挥作用?

编辑: 这就是我最终实施的...

public class TimedActivity extends Activity
{
    //member variables
    private Timer mTimerSeconds;
    private int mIntIdleSeconds;
    private boolean mBoolInitialized=false;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onDestroy()
    {
        if (mTimerSeconds != null)
        {
            mTimerSeconds.cancel();
        }
        super.onDestroy();
    }

    public void onTouch()
    {
        mIntIdleSeconds=0;
    }

    /** start the idle timer */
    public void startIdleTimer()
    {
        if (mBoolInitialized == false)
        {
            mBoolInitialized = true;

            //initialize idle counter
            mIntIdleSeconds=0;

            //create timer to tick every second
            mTimerSeconds = new Timer();
            mTimerSeconds.schedule(new TimerTask()
            {
                @Override
                public void run()
                {
                    timerSecondsCounter();
                }
            }, 0, 1000);
        }
    }

    /** called every second to count idle time and to update clock on Welcome screen */
    private void timerSecondsCounter()
    {

        mIntIdleSeconds++;

        if (mIntIdleSeconds == Constants.MAX_IDLE_TIME_SECONDS)
        {
            //idle time long enough to launch standby activity
            final Intent intent = new Intent(this, what.ever.com.Idle.class);
            startActivity(intent);
        }

    }

}

要使用此 ActivityTimed,请在您启动的 Activity 中执行以下操作:

public class ActivitySelect extends TimedActivity implements OnTouchListener
{
    //UI references
    private LinearLayout mLinearLayout;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);//triggers TimedActivity::onCreate()
        setContentView(R.layout.select);

        //get references to all of your widgets
        mLinearLayout = (LinearLayout) findViewById(R.id.select_linearlayout_main);

        //set your widgets as touchable
        mLinearLayout.setOnTouchListener(this);

        //start the idle timer
        super.startIdleTimer();
    }

    @Override
    protected void onDestroy()
    {
        //this is very important here ;-)
        super.onDestroy();
    }

    public boolean onTouch(View v, MotionEvent event)
    {
        final int actionPerformed = event.getAction();

        //reset idle timer
        // put this here so that the touching of empty space is captured too
        //  it seems that LinearLayout doesn't trigger a MotionEvent.ACTION_UP or MotionEvent.ACTION_MOVE
        if (actionPerformed == MotionEvent.ACTION_DOWN)
        {
            super.onTouch();
        }

        return false;//do not consume event!
    }
}

【问题讨论】:

  • 这个超时是为了使某种会话过期,还是将用户发送到登录屏幕?如果是我也遇到过同样的问题,有不同的解决方案。
  • 是的,一旦发生超时,就会自动启动不同的活动 - 即登录屏幕、屏幕保护程序等......一些空闲屏幕
  • 然后你可以通过使用默认属性来避免这种方法:finishOnTaskLaunch on all but Login (登录活动无法完成,必须在堆栈上。你还可以检测屏幕是否关闭,以及立即发送到登录屏幕。
  • NeTeInStEiN,如果你有时间,你能用代码 sn-ps 演示你的解决方案吗?我已经搜索了一段时间,很多人都想为活动实现某种空闲/超时机制——看看你的解决方案会很有帮助。

标签: android


【解决方案1】:

编辑:好吧,我之前试图建议的并不是我的意思......

ActivitySelectonCreate()方法中(例如)放上代码...

setContentView(/* Id of layout file for ActivitySelect */);
mLinearLayoutMain = (LinearLayout) findViewById(/* Id of LinearLayout for ActivitySelect */);

这意味着ActivitySelect 将设置其内容视图并将继承的mLinearLayoutMain 成员设置为视图。

onStart() 中为TimedActivity 放...

mLinearLayoutMain.setOnTouchListener(this);

您可能还想在TimedActivity 中的onTouch() 方法上使用@Override

【讨论】:

  • 在吃午饭的时候,我认为通过在 TimedActivity 中实现诸如“setViewRoot”之类的函数,将 LinearLayout 的引用传递给超类 (TimedActivity) 可能值得一试。然后用 super.setViewRoot(reference to LinearLayout); 调用它我午饭后试试。
  • 我最终做的是根本没有将 LinearLayout 的引用传递给 TimedActivity。相反,我只在 TimedActivity 和一个 void onTouch() 中实现了计时逻辑。这个 onTouch() 负责将计数器重置为 0。然后,ActivitySelect 扩展了 TimedActivity 实现了 OnTouchListener。所有的 onTouch(View v, MotionEvent event) 回调然后调用 super.onTouch();这很好用,也尽可能地保持代码解耦。
  • 我会接受你的回答,因为它可能会起作用 - 我在午餐时间也有同样的想法,但我更喜欢我目前的实现。
  • @Someone:好的,这很酷——显然你需要选择最适合你的解决方案。感谢您的接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 2021-03-07
相关资源
最近更新 更多