我去年做了一个android应用程序,它工作得很好,我被重新分配到开发应用程序。
但是用户的注册已经停止。至于为什么,我也不知道。
这是我的开始屏幕,用户注册的活动:
public class Prompt extends Activity {
public EditText u, p, e;
public String username, password, emailadd;
public Button createClient;
final Context context = this;
public TextView registerErrorMsg;
// JSON Response node names
private static String KEY_SUCCESS = "success";
@SuppressWarnings("unused")
private static String KEY_ERROR = "error";
@SuppressWarnings("unused")
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_NAME = "name";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.prompt);
// Importing all assets like buttons, text fields
u = (EditText) findViewById(R.id.username);
p = (EditText) findViewById(R.id.Password);
e = (EditText) findViewById(R.id.emailAddress);
createClient = (Button) findViewById(R.id.createClient);
registerErrorMsg = (TextView) findViewById(R.id.register_error);
u.setText("usernametest");
p.setText("passwordtest");
e.setText("TEST@gmail.com");
//Toast.makeText(getApplicationContext(), "...", Toast.LENGTH_LONG).show();
createClient.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
username = u.getText().toString();
password = p.getText().toString();
emailadd = e.getText().toString();
UserFunctions userFunction = new UserFunctions();
//Toast.makeText(getApplicationContext(), username+" "+password+" "+emailadd, Toast.LENGTH_LONG).show();
//now we have text input, validate them
if(username.length() < 5 || password.length() < 5 || emailadd.length() < 5){
//minimum input for each field is > 5 characters
registerErrorMsg.setText("Username, password and email must have must than 5 characters");
}
else{
//if validated correctly upload
JSONObject json = userFunction.registerUser(username, emailadd, password);
Log.e("JSON RESULT", "JSON result: " + json);
//successfully make the check file and redirect to the homepage
try {
String FILE_NAME = "filename.txt";
FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_WORLD_READABLE);
try{
fos.write(username.getBytes());
}catch (IOException e){
e.printStackTrace();
}
fos.close();
//if all complete, redirect to home page
Intent intent2 = new Intent(Prompt.this, StrategicEnergyActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent2);
finish();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
}
这是我的JSON解析器类来处理从web服务返回的JSON:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url, List<NameValuePair> params) {
Log.e("TESTTTT", " " + params.get(0) + " " + params.get(1) + " " + params.get(2) + " " + params.get(3));
// Making HTTP request
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
json = sb.toString();
Log.e("JSON", json);
}
catch (Exception e){
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try{
jObj = new JSONObject(json);
}
catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
这是我的用户函数类,类做数据处理/方法调用:
public class UserFunctions {
private JSONParser jsonParser;
private static String registerURL = "http://www.website.com/api/index.php?";
private static String register_tag = "register";
// constructor
public UserFunctions(){
jsonParser = new JSONParser();
}
/**
* function make Login Request
* @param name
* @param email
* @param password
* */
public JSONObject registerUser(String name, String email, String password){
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("tag", register_tag));
params.add(new BasicNameValuePair("name", name));
params.add(new BasicNameValuePair("email", email));
params.add(new BasicNameValuePair("password", password));
Log.e("Credentials", "Username: " + name + "'nEmail: " + email + "'nPassword: " + password);
//Toast.makeText(getParent(), name+" "+email+" "+password, Toast.LENGTH_LONG).show();
JSONObject json = jsonParser.getJSONFromUrl(registerURL, params);
return json;
}
}
下面是我的web服务的代码:
<?php
print_r($_POST);
$tag = "register";
// include db handler
require_once 'include/DB_Functions.php';
$db = new DB_Functions();
// response Array
$response = array("tag" => $tag, "success" => 0, "error" => 0);
// check for tag type
if ($tag == 'register') {
// Request type is Register new user
$name = $_POST['name'];
$email = $_POST['email'];
$password = $_POST['password'];
// check if user is already existed
if($db->isUserExisted($email)){
// user is already exists - error response
$response["error"] = 2;
$response["error_msg"] = "User Already Exists";
echo json_encode($response). "User Already Exists";
}
else{
// store user
$user = $db->storeUser($name, $email, $password);
if($user){
// user stored successfully
$response["success"] = 1;
$response["uid"] = $user["unique_id"];
$response["user"]["name"] = $user["name"];
$response["user"]["email"] = $user["email"];
$response["user"]["created_at"] = $user["created_at"];
$response["user"]["updated_at"] = $user["updated_at"];
echo json_encode($response). "User Stored Successfully";
}
else{
// user failed to store
$response["error"] = 1;
$response["error_msg"] = "Error occured in Registration";
echo json_encode($response);
}
}
}
else{
echo "Invalid Request";
}
?>
最后这是当前抛出给我的错误,它发生在JSONParser类的sb.append(line)行:
05-21 16:35:46.304: E/Buffer Error(4278): Error converting result java.lang.NullPointerException
05-21 16:35:46.308: E/JSON Parser(4278): Error parsing data org.json.JSONException: End of input at character 0 of
05-21 16:35:46.308: E/JSON RESULT(4278): JSON result: null
有人能发现我在这里做错了什么吗?无论如何,我都将非常感谢你的帮助。
提前感谢!
当您尝试解析JSON中没有任何内容时,会发生错误。例如,如果你的手机没有连接到互联网,而你试图连接到你的服务器,你会看到类似的响应。没有数据要解析所以你会得到一个JSONException
。
我猜这与你的I/O函数不在后台线程上有关。根据所提供的代码,您将在主UI线程的JSONParser类中运行HttpPost
。自API 11以来,这是不允许的。因此,您将没有值可以解析并抛出JSONException
。
尝试将此函数移动到AsyncTask
。如果在任务的doInBackground
方法中执行HttpPost
,则可以消除错误。这里是AsyncTask
相关的android文档的链接。他们提供了一些有用的代码示例。
AsyncTask
的基本结构如下:
private class DownloadFilesTask extends AsyncTask<URL, Void, Long> {
protected Long doInBackground(URL... urls) {
//stuff to do in background
return result;
}
protected void onPostExecute(Long result) {
//stuff that runs on the UI thread using the result of background thread
}
}
在这个例子中,取自android文档,你可以看到一些关键参数。(1) <中指示的任务的参数/返回值;> (2) doInBackground
方法,令人震惊的是,在后台线程上运行;(3)onPostExecute
方法,在doInBackground
方法完成后在UI线程上运行。onPostExecute
接受doInBackground
返回的值作为参数。如果你注意到,该参数的类型对应于<在上课开始的时候。>
你将不得不玩周围这适合你的代码,但基本的想法是,任何I/O函数-像你的HttpPost
发生在后台线程。任何UI更新,如改变TextView
中的文本,使用Toast
或移动屏幕上的东西都发生在onPostExecute
中。换句话说,在doInBackground
中下载你需要的东西并返回结果-在你的情况下是一些JSON/字符串-到onPostExecute
,在那里你可以通知用户更改,例如他们是否成功注册。
如何传递值给AsyncTask
你在评论中问了另一个问题,关于如何将URL
传递给AsyncTask
。将值传递给AsyncTask
发生在用于启动任务的execute()
方法中。因为AsyncTask
是它自己的类,所以需要首先创建任务的实例
DownloadFilesTask t = new DownloadFilesTask();
创建任务实例后,使用execute()
方法启动该任务。在这里,您可以传递您希望任务在doInBackgroundMethod
中接收的值。
t.execute(myUrl);
要传递多个值,只需将它们以逗号分开添加
t.execute(myUrl1, myUrl2, myUrl3);
要检索传入的值,您可以在doInBackground
方法中访问它们。AsyncTask
接受称为varargs
的参数。这些基本上是特定类型的值列表。在您的示例中,它们将是url。要访问它们,您可以通过索引获取值。
URL first = urls[0]
例如,引用您传递给AsyncTask
的第一个URL值。您用来检索它的名称对应于…后面的名称。作为doInBackground
方法的参数。例如,如果你将一个URL传递给AsyncTask
然后想在getWhatever方法中检索它你只需使用
getWhatever(urls[0]);
如果有多个URL并且这是一个迭代过程你可以使用for循环或任何其他方法遍历所提供的URL