Android - 如何继续提示对话框

时间:2014-03-15 23:30:23

标签: java android http android-asynctask android-dialog

简介

我想要完成的事[听起来]很简单。我想提示用户使用登录对话框,直到用户成功进行身份验证。

我打算做的是使用AsyncTask进行数据处理和Web请求,但这很快就变成了一场噩梦;很可能是由于我缺乏Android经验。

但是,我知道这可以做到,正如我之前在其他应用中看到的那样。


我想要完成的事情

问题是如何?我知道自己想做什么:

1. Initially prompt a user to login.
2. Send authentication data.
3. If successful, continue the application.
4. If unsuccessful, reprompt the user until success.

到目前为止我有什么

到目前为止,我的AsyncTask(LoginTask)将处理Web请求和登录数据:

public class LoginTask extends AsyncTask<String, Void, App.STATUS>
{
    private boolean m_proceed = false;
    private String m_username, m_key;

    @Override
    protected void onPreExecute()
    {
        // Check if there is a dialog on screen. //
        m_proceed = !App.DIALOG_ONSCREEN;
    }

    @Override
    protected App.STATUS doInBackground(String ... p_args)
    {
        // Do not do this if a dialog is on screen. //
        if(!m_proceed)
            return App.STATUS.DENIED;

        // Make a web request. //
        try
        {
            URL t_url = new URL("https://mysite.com/api/login");
            HttpsURLConnection t_con = (HttpsURLConnection)t_url.openConnection();

            t_con.setRequestMethod("POST");
            t_con.setRequestProperty("User-Agent", "Mozilla/5.0");

            t_con.setDoOutput(true);
            DataOutputStream t_wr = new DataOutputStream(t_con.getOutputStream());
            t_wr.writeBytes("username="+p_args[0]+"&password="+p_args[1]);
            t_wr.flush();
            t_wr.close();

            t_con.connect();

            BufferedReader t_in = new BufferedReader(new InputStreamReader(t_con.getInputStream()));

            String t_input_line;
            StringBuffer t_response = new StringBuffer();

            while((t_input_line = t_in.readLine()) != null) 
            {
                t_response.append(t_input_line);
            }

            t_in.close();

            // If denied, return failed. If accepted, set the username and key. //
            if(t_response.toString().equals("DENIED"))
                return App.STATUS.FAILED;
            else
            {
                m_key = t_response.toString();
                m_username = p_args[0];
            }

            return App.STATUS.ACCEPTED;
        }
        catch(Exception err)
        {
            System.err.println(err.getMessage());
        }

        return App.STATUS.FAILED;
    }

    @Override
    protected void onPostExecute(App.STATUS p_status)
    {
        // Authenticate the user if the username and key are valid. //
        if(p_status == App.STATUS.ACCEPTED)
            App.acceptCredentials(m_username, m_key);

        // The dialog is no longer on the screen. //
        App.DIALOG_ONSCREEN = false;
    }
}

主要活动(HomeActivity)会提示用户未经过身份验证,并会显示内容:

public class HomeActivity extends Activity
{
    @Override
    public void onCreate(Bundle p_data)
    {
        // Basic crap... //
        super.onCreate(p_data);
        setContentView(R.layout.activity_home);

        // Are we authenticated? //
        if(!App.isAuthenticated())
        {
            // Create the dialog. //
            LayoutInflater t_infl = LayoutInflater.from(this);
            View t_login_view = t_infl.inflate(R.layout.login_dialog, null);

            AlertDialog.Builder t_builder = new AlertDialog.Builder(this);
            t_builder.setTitle("Login").setView(t_login_view).setPositiveButton("Login", new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    // What should go here? //
                }
            });

            t_builder.create();
        }

        // How do I keep checking if the user is not authenticated, and keep showing the dialog as such? //
    }
}

我需要帮助

我的主要问题是如何设计我的程序,以便我可以轻松地显示登录对话框,直到用户成功通过身份验证? 我想到了使用while循环,但它会继续显示对话框并妨碍性能。当异步和同步任务协同工作时,这非常棘手。

我不是在寻找直接的代码,但我们非常感谢您的一般见解。

感谢您抽出宝贵时间阅读本文并感谢您的帮助!


解决方案

HomeActivity.java

private void promptLogin()
{
    final Context t_main_context = this;

    // Create the dialog. //
    LayoutInflater t_infl = LayoutInflater.from(this);
    final View t_login_view = t_infl.inflate(R.layout.login_dialog, null);

    final AlertDialog t_dialog = new AlertDialog.Builder(this)
            .setTitle("Login")
            .setCancelable(false)
            .setView(t_login_view)
            .setPositiveButton("Login", null)
            .create();
    t_dialog.show();

    t_dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View t_view)
        {
            String t_username = ((EditText)t_login_view.findViewById(R.id.in_username)).getText().toString(),
                    t_password = ((EditText)t_login_view.findViewById(R.id.in_password)).getText().toString();

            try
            {
                new LoginTask(t_main_context, t_dialog).execute(t_username, t_password);
            }
            catch(Exception err)
            {
                err.printStackTrace();
            }
        }
    });
}

@Override
public void onCreate(Bundle p_data)
{
    // Basic crap... //
    super.onCreate(p_data);
    setContentView(R.layout.activity_home);

    // Are we authenticated? //
    if(!App.isAuthenticated())
        promptLogin();
}

LoginTask.java

private String m_username, m_key;

private Context m_context;
private AlertDialog m_dialog;
private ProgressDialog m_loading;

public LoginTask(Context p_context, AlertDialog p_dialog)
{
    m_context = p_context;
    m_dialog = p_dialog;

    m_loading = ProgressDialog.show(m_context, "", "Logging in...", true);
}

@Override
protected App.STATUS doInBackground(String ... p_args)
{
    // Make a web request. //
    try
    {
        URL t_url = new URL("https://mysite.com/api/login");
        HttpsURLConnection t_con = (HttpsURLConnection)t_url.openConnection();

        t_con.setRequestMethod("POST");
        t_con.setRequestProperty("User-Agent", "Mozilla/5.0");

        t_con.setDoOutput(true);
        DataOutputStream t_wr = new DataOutputStream(t_con.getOutputStream());
        t_wr.writeBytes("username="+p_args[0]+"&password="+p_args[1]);
        t_wr.flush();
        t_wr.close();

        t_con.connect();

        BufferedReader t_in = new BufferedReader(new InputStreamReader(t_con.getInputStream()));

        String t_input_line;
        StringBuffer t_response = new StringBuffer();

        while((t_input_line = t_in.readLine()) != null) 
        {
            t_response.append(t_input_line);
        }

        t_in.close();

        // If denied, return failed. If accepted, set the username and key. //
        if(t_response.toString().equals("DENIED"))
            return App.STATUS.FAILED;
        else
        {
            m_key = t_response.toString();
            m_username = p_args[0];
        }

        return App.STATUS.ACCEPTED;
    }
    catch(Exception err)
    {
        System.err.println(err.getMessage());
    }

    return App.STATUS.FAILED;
}

@Override
protected void onPostExecute(App.STATUS p_status)
{
    m_loading.dismiss();

    // Authenticate the user if the username and key are valid. //
    if(p_status == App.STATUS.ACCEPTED)
    {
        App.acceptCredentials(m_username, m_key);
        m_dialog.dismiss();
    }
    else
        Toast.makeText(m_context, "Login failed", Toast.LENGTH_SHORT).show();
}

所以我在promptLogin() HomeActivity.java中所做的是我覆盖onClickListener上的按钮,因此除非被t_dialog.dismiss()关闭,否则对话框不会关闭。然后我将Web请求发送到LoginTask并将对话框作为参数传递,这样对话框才会关闭,直到我解除对话框为止。

我只会在接受凭据时关闭对话框,您可以在onPostExecute()中看到。

通过这种方式,对话框保持在屏幕上,直到用户成功登录,这是我正在寻找的行为。

感谢大家的帮助!

2 个答案:

答案 0 :(得分:0)

您必须创建一个处理登录的活动,另一个活动是您的主要活动。如果登录失败,则没有任何反应,如果成功则启动第二个活动。无需复杂的设置。 您还可以查看Volley库,轻松实现http连接。

答案 1 :(得分:0)

<强> 1。最初提示用户登录。

使用setCancelable(false)继续提示此处的对话框,因此用户不会取消登录过程。然后在用户必须单击的按钮上创建View.OnclickListner,以便将数据发送到您的服务器。我们说Login按钮。

AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Delete entry")
        .setMessage("Are you sure you want to delete this entry?")
        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) { 
                // send data here with AsyncTask
            }
         })
        .setIcon(R.drawable.ic_my_icon);
    builder.setCancelable(false);
builder.show();

<强> 2。发送身份验证数据。

在此处使用AsyncTask,在doInBackgroud()方法中执行发送任务,并返回onPostExecute()内容以了解身份验证是否成功。如果成功,则关闭对话框,如果没有,则保留对话框并等待用户再次单击Login按钮。

protected void onPostExecute(Boolean result) {

    if(result) {
        // he is now authenticated, dismiss dialog and continue in your app
        dialog.dismiss();
    } else {
        // nothing to do, until he succeed
    }    
}

第3。如果成功,请继续申请。

使用dismiss()方法点击此处的对话框。

<强> 4。如果不成功,请重新启动用户直至成功。

不要做任何事情,让对话框显示,直到验证过程成功。你也可以向用户展示一些东西(吐司,图像等)告诉他他还没有登录。

希望你能清楚。