我想要完成的事[听起来]很简单。我想提示用户使用登录对话框,直到用户成功进行身份验证。
我打算做的是使用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()
中看到。
通过这种方式,对话框保持在屏幕上,直到用户成功登录,这是我正在寻找的行为。
感谢大家的帮助!
答案 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。如果不成功,请重新启动用户直至成功。
不要做任何事情,让对话框显示,直到验证过程成功。你也可以向用户展示一些东西(吐司,图像等)告诉他他还没有登录。
希望你能清楚。