6

我有一个应用程序启动Splash activity screen5 秒然后打开Login activity screen,然后在输入正确的用户名和密码后打开,Menu activity (listActivity)然后每行单击打开MyCity activity

更新:

我想要得到的是:无论您在我的应用程序中的哪个位置,并且您出于任何原因离开我的应用程序,不仅是在您按下主页按钮时,而且例如:

  1. 您按主页按钮检查另一个应用程序然后想返回我的应用程序。

  2. 你有通知在 whatsup 或电子邮件上显示新消息,你打开你的 whatsup 或打开电子邮件,然后返回我的应用程序。

3-你离开你的手机一段时间然后你想再次检查我的应用程序。

4-您按电源按钮关闭手机(锁定屏幕),然后打开锁并想要返回我的应用程序。

我的意思是,任何时候您出于任何原因离开我的应用程序,但不按返回按钮,这将退出整个应用程序然后想要再次返回到我的应用程序,必须向您打开登录屏幕以重新输入您的用户名和密码。

我呼吁finish();启动 Splash 活动和 Login 活动。

我试过:android:clearTaskOnLaunch="true"在清单中的登录活动中,但它没有。

任何建议将被认真考虑,

请编写完整的工作代码。

登录活动:

 public class Login extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login);

    Button b = (Button) findViewById(R.id.loginbutton);

  b.setOnClickListener(new OnClickListener() {

  public void onClick(View v) {

    EditText username = (EditText) findViewById(R.id.login);
    EditText password = (EditText) findViewById(R.id.password);

     if(username.getText().toString().length() > 0 && password.getText().
             toString().length() > 0 ) {
if(username.getText().toString().equals("test") && password.getText().
             toString().equals("test")) {


    Intent intent = new Intent(Login.this, Menu.class);
    startActivity(intent);
       finish(); }
            }   }               
                    });  }  }

菜单活动:

  public class Menu extends ListActivity {

      String classes[] = { "City1", "City2", "City3", "City4", "City5"};

          @Override
      protected void onCreate(Bundle savedInstanceState) {
         // TODO Auto-generated method stub
         super.onCreate(savedInstanceState);

      setListAdapter(new ArrayAdapter<String>(Menu.this,
        android.R.layout.simple_list_item_1, classes));
                                   }

     @Override
       protected void onListItemClick(ListView l, View v, int position, long id) {
         // TODO Auto-generated method stub
          super.onListItemClick(l, v, position, id);
         String cheese = classes[position];
   try {
    Class ourClass = Class.forName("com.test.demo.MyCity");
    Intent ourIntent = new Intent(Menu.this, ourClass);
    ourIntent.putExtra("cheese", cheese);
         startActivity(ourIntent);
           } catch (ClassNotFoundException e) {
        e.printStackTrace();
                            }
                    }}

我的城市活动:

   public class MyCity extends Activity {
TextView tv1;
String city;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.city);  

    initializeTextViews();}

private void initializeTextViews() {

    tv1=(TextView)findViewById(R.id.city_tv);
     city=getIntent().getStringExtra("cheese");

if(city.equalsIgnoreCase("City1")){

        tv1.setText(Html.fromHtml(getString(R.string.city1)));}


    else if(city.equalsIgnoreCase("City2")){

        tv1.setText(Html.fromHtml(getString(R.string.city2)));}


    else if(city.equalsIgnoreCase("City3")){

        tv1.setText(Html.fromHtml(getString(R.string.city3)));}


    else if(city.equalsIgnoreCase("City4")){

        tv1.setText(Html.fromHtml(getString(R.string.city4)));}


    else if(city.equalsIgnoreCase("City5")){

        tv1.setText(Html.fromHtml(getString(R.string.city5)));}


    }}

我的清单:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.demo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name=".Splash"
            android:label="@string/app_name">   
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".Login"
            android:label="@string/app_name" 
                 android:clearTaskOnLaunch="true">
            <intent-filter>
                <action android:name="com.test.demo.LOGIN" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:name=".Menu"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.test.demo.MENU" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

              <activity
            android:name=".MyCity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.test.demo.MYCITY" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

第二次更新:我达到了我想要的一半,但仍有一些步骤我无法实现,解释如下:

通过申请 android:clearTaskOnLaunch="true"Splash 活动,

并防止菜单活动上的后退按钮行为:

  @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
       moveTaskToBack(true);
       return true;
            }
    return super.onKeyDown(keyCode, event);
                    } }

所以现在当按下主页按钮离开我的应用程序然后返回我的应用程序时:

直接进入登录活动

但现在的主要目标是:

如果 :

离开手机时屏幕锁定,或轻按电源按钮锁定手机。

或者

来自通知的已打开消息

或者

来自通知的已打开电子邮件

或者

你有CALL并回答它,

然后返回我的应用程序,它不会进入登录活动,但您将返回您之前的页面。

任何建议,谢谢。

泰德更新:

我使用了另一个代码来覆盖主页按钮并控制后退按钮而不是应用:android:clearTaskOnLaunch="true"到清单中的 Splash 活动,只需将向下代码应用于菜单活动:

     @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
      if (keyCode == KeyEvent.KEYCODE_BACK) {
       moveTaskToBack(true);
         return true;}

    else if (keyCode == KeyEvent.KEYCODE_HOME) { 
     Intent i=new Intent(Menu.this,Login.class);
       startActivity(i);
          finish();
        return true;}
    return super.onKeyDown(keyCode, event);}
4

15 回答 15

8

如果我理解你的话,你的目标是用户必须再次输入用户名和密码,当他们回到你的应用程序时。所以我认为实现这一点的最合乎逻辑的方法是在所有活动onResume()方法中添加一个检查,以查看您是否有用户名和密码,如果没有,只需转到登录活动。最简单的方法是让 BaseActivity 实现检查并让您的所有其他活动(spash 和登录除外)从该 BaseActivity 继承。

在伪java代码中

class BaseActivity extends Activity {

    onResume() {
        super.onResume();
        if (!havingUsernameAndPassword()) {
            startActivity(loginActivity);
            finish();
        }
    }
}

class AnyOfYourActivitiesExceptSpashAndLogin extends BaseActivity {

    onResume() {
        super.onResume();
        // ... further code
    }

    // ... further code
}

当然,实施havingUsernameAndPassword()取决于您如何在登录活动中存储用户名和密码。一个非常简单的方法是将它们存储在一些静态类成员中,这样只要应用程序运行它们就会存在。

更新:一个更具体的例子

我制作了一个新示例,还展示了如何在登录时保存登录数据,以便以后检查。实际上,只有一个标志 'loggedIn' 和一些用户 ID 会更有意义,但这取决于你的实现,所以我会在这里坚持使用用户名/密码。

class SimpleDataHolder {
    public static String username = null;
    public static String password = null;
}

class LoginActivity extends Activity {

    // ...
    // when user has entered valid username/password, store them in SimpleDataHolder:
    SimpleDataHolder.username = username;  // <-- store username entered
    SimpleDataHolder.password = password;  // <-- store password entered
}

class BaseActivity extends Activity {

    onResume() {
        super.onResume();
        if (SimpleDataHolder.username == null || SimpleDataHolder.password == null) {
            startActivity(loginActivity); // <-- go to login
            finish();                     // <-- end current activity
        }
    }
}

class AnyOfYourActivitiesExceptSpashAndLogin extends BaseActivity {

    // ... your existing code (if any)

    onResume() {
        super.onResume();  // <-- this calls BaseActivity.onResume() which checks username/password
        // ... your existing code (if any)
}
于 2012-11-02T10:06:42.920 回答
4

应用程序不能在不修改框架代码的情况下重新路由主页按钮。抱歉,这是不可能的……

于 2012-10-27T23:47:35.417 回答
4

对于您的第二个更新问题,我建议您覆盖OnResume()方法,但您必须小心您在其中所做的事情。我还建议您研究一下android 生命周期是如何工作的。

于 2012-10-31T13:52:33.643 回答
3

这是我的建议:

有一个keyinSharedPreferences称为exit。在onCreate()设置中exit的值为false

public void onCreate(Bundle ..)
{
 SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(context);
 SharedPreferences.Editor editor=preferences.edit();
 editor.putString("exit","false");
 editor.commit();
 .....  
}

然后onResume()检查exit的值。如果是真的,把用户带到登录屏幕,否则什么也不做。

public void onResume()
{
 super.onResume();
 SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(context);
 String exit=preferences.getString("exit","");
 if(exit.equals("true"))
 {
   Intent i=new Intent(this_activity.thi,login_activity.class);
   startActivity(i);
  finish()
 }
}

然后onPause()将 exit 的值设置为true

public void onPause()
{
 super.onPause();
 SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(context);
     SharedPreferences.Editor editor=preferences.edit();
     editor.putString("exit","true");
     editor.commit();
}

你说你已经照顾好了backbutton。那么这应该做到。您的应用程序将始终返回登录屏幕。

于 2012-11-02T03:58:06.887 回答
2

另一种解决方法是创建一个活动(FinisherActivity)并在其 onCreate() 方法中调用 finish()。然后,每当您需要在按下主页按钮或后退按钮时完成一项活动并防止其停留在堆栈上时,只需使用 Intent 调用 FinisherActivity 。但请记住为 Intent.FLAG_ACTIVITY_CLEAR_TOP 的意图设置标志...我知道它不是一种有效的方法,但它应该可以工作..

于 2012-10-30T12:13:41.010 回答
2

这是我想出的解决方案。

请在博文末尾下载项目并进行测试。

测试:

  • 运行安卓 4.0.4 的三星 S3
  • 运行 android 2.3.1 的模拟器

基本思想:我们将创建一个 RequireLoginActivity,它将被除 LoginActivity 之外的所有活动扩展。

调用onResume函数时应捕获三种情况:

  1. 使用 startActivity 从一个 RequireLoginActivity 跳转到另一个 RequireLoginActivity。
  2. 通过完成当前活动,从一个 RequireLoginActivity 跳回到前一个 RequireLoginActivity。
  3. 隐藏后返回 RequireLoginActivity(我们应该在这里显示登录信息!)

我的解决方案的基本思想是有 2 个计数器:已启动活动的数量 ( startCounter ) 和已暂停活动的数量 ( pauseCounter )。每次活动开始时,我们都会增加startCounter。同样,当一个活动暂停时,pauseCounter应该增加。在我们的onResume函数中,我们将通过比较 2 个计数器来决定是否去登录。如果两个计数器相等,我们将 gotoLogin() !

让我解释一下:在任何时候,案例 1 都可以被捕获,因为在开始新的活动时,我们的startCounter总是比pauseCounter大1。这是真的,因为我们总是有一个额外的活动开始但没有暂停。

此外,案例 3 很容易捕获,因为一旦您离开我们的应用程序,例如,使用 HOME 按钮,我们将增加pauseCounter并且 2 个计数器将变得相等。一旦应用程序恢复,onResume将决定gotoLogin ()。

案例 2 有点棘手,但也很简单。诀窍是重写finish () 函数并减少startCounter一次和pauseCounter两次。请记住,当完成活动时,会调用onPause并且我们的计数器是相等的。现在通过减少startCounter一次和pauseCounter两次,我们最终返回到上一个活动的计数器值,并且当上一个活动恢复时, startCounter将保持比pauseCounter大 1。

于 2012-11-01T10:09:59.540 回答
1

其实我不认为我确定你到底在问什么,你想按下你的 android 设备中内置的 Home 键并开始一个活动吗?

主键监听器

试试这个:如果它有效,那就太棒了,只需通过那里的意图来调用您的登录活动

@Override
    public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.KEYCODE_HOME) { 
            Toast.makeText(MainActivity.this, "Home Key is pressed
                    Toast.LENGTH_LONG).show();
            return true;
        }
        Toast.makeText(MainActivity.this, "Didnt work", Toast.LENGTH_SHORT)
                .show();
        return super.dispatchKeyEvent(e);
    };
于 2012-10-12T23:51:58.830 回答
1

您不能覆盖主页按钮的默认行为。您可以通过单击返回按钮来获得所需的结果,主页按钮的默认行为是转到主屏幕。我的建议覆盖后退按钮。然后正确使用意图和设置标志,您可以转到登录屏幕。

   @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        super.onKeyDown(keyCode, event);
        switch(keyCode)
        {
        case KeyEvent.KEYCODE_BACK:
        Intent i= new Intent("yourpackage.login"); 
        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_NO_HISTORY); 
        startActivity(i);
        finish();
        break;  
        }
        return super.onKeyDown(keyCode, event);
    }
于 2012-10-13T06:27:55.843 回答
1

你要问的是反对android的工作方式。

当用户按下主页按钮时,他希望当他返回应用程序时,一切都将保持原样,除非他很长时间不在那里,或者他运行了一个资源消耗应用程序。

就像在 windows 上一样,当您单击 ALT+TAB 时,您不会期望在电子邮件客户端(或 messenger 或您使用的任何应用程序)上看到登录。

在任何情况下,您都可以将 onWindowFocusChanged 与任何活动功能(onResume,onStart,onRestart,onPause,onStop,...)一起使用,并且只处理您希望使用的相关情况。

于 2012-10-22T23:50:50.837 回答
1

这是不可能的,因为主页按钮是调用启动器应用程序独有的,但您可以将您的应用程序作为启动器应用程序,例如在信息亭模式下运行,查看

要打开启动器活动的活动,请将其添加到 manifest.xml 上的 itentfilter

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
于 2012-10-28T05:58:43.830 回答
1

您的代码几乎是正确的:要在启动应用程序时清除活动堆栈,您应该添加android:clearTaskOnLaunch="true" 到您的根活动中,即Splash,不是Login(它将是第一个运行的,请参阅这个关于确定根活动的问题)!

文档中:

该属性仅对启动新任务的活动(根活动)有意义;任务中的所有其他活动都会忽略它

因此,如果您将清单中的属性从 移动LoginSplash,它应该可以工作,您的应用程序将始终以启动画面开始。

更新:要在来电、屏幕锁定或通知时重新启动您的应用程序,您必须将(此处android:noHistory="true"的文档)添加到您的所有其他活动中,或调用它们的所有方法。finish()onPause()

值得一提的是,我们的答案是如此不同和复杂,因为你想要实现的完全违背核心 Android 概念(例如,这里是一篇关于退出应用程序的好文章),所以真的,不要在你的私人之外做任何这样的事情应用程序。

于 2012-10-28T09:55:00.663 回答
1

很难确切地说出您在问什么,但是我相信这就是您要寻找的:如果应用程序已经在内存中,如何使启动画面不加载。总结我在那里的帖子:

这是一个设计问题。您的启动器活动不应该是您的启动屏幕活动。相反,在您的主要活动的 onCreate 方法中打开您的启动活动。这样,如果它是全新打开的,则会调用 onCreate 并显示初始屏幕。否则,如果应用程序只是恢复,它调用 onResume,则不会调用打开启动屏幕活动。

然后您可以将清单更改为:

<activity
        android:name=".ui.MainActivity"
        android:noHistory="true"
        android:screenOrientation="portrait"
        android:label="@string/app_name">

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

<activity android:name=".ui.SplashActivity"/>
于 2012-10-29T05:23:50.557 回答
1

您是否尝试过 Android Manifest 中的android:noHistory活动属性(针对您的每个活动)?这听起来正是您正在寻找的。

于 2012-10-29T19:53:02.627 回答
1

您应该调用除登录活动之外finish()的所有活动方法。onPause()你可以调用startActivity(new Intent (this, LoginPage.this))他们的onResume()方法。因此,每当活动进入前台时,用户将再次被重定向到登录页面。

于 2012-11-02T09:16:50.650 回答
0

我的一点点努力可能会对你有所帮助,我已经成功覆盖HOME按钮(Android 4.0以下)

您可以根据您的要求塑造代码。

回答 SO

来源在 GITHUB

由于您现在可以处理主页按钮,因此您可以轻松创建自己的逻辑来执行您的应用程序流程。

这是你的目标事件

@Override
    public boolean dispatchKeyEvent(KeyEvent event) {

        if ( (event.getKeyCode() == KeyEvent.KEYCODE_HOME) && isLock) {
             //Logic when Home button pressed
            return true;
        }
        else
            return super.dispatchKeyEvent(event);
    }

希望这肯定会满足我们的要求。

注意:所有这些都是为了Home为您可以管理的其他人捕获 Button

于 2012-11-01T04:27:43.530 回答