Ошибка получения JSON через HTTPS

Ответить
ironz
Сообщения: 3
Зарегистрирован: 24 июн 2014, 22:58

Ошибка получения JSON через HTTPS

Сообщение ironz » 24 июн 2014, 23:18

Пол дня бьюсь, не могу понять как решить проблему, имею логин систему вида:

[syntax=java]https://www.app.com/app/login.cgi + "?login=" + email + "&password=" + password + "&sign=" + hexString.toString();[/syntax]

Реализовано это следующим образом:

[syntax=java]private class ProcessLogin extends AsyncTask<Void, Void, Void> {

String email, password, key;

@Override
protected void onPreExecute() {
super.onPreExecute();

inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.pword);
email = inputEmail.getText().toString();
password = inputPassword.getText().toString();
key = "EaG6wB6VlWuemy_b0nq_HsPyYKkOaA";

}

@Override
protected Void doInBackground(Void... params) {

String conc = email + password + key;

MessageDigest md5 = null;
StringBuilder hexString = new StringBuilder();

try {
md5 = MessageDigest.getInstance("md5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

md5.reset();
md5.update(conc.getBytes());

byte messageDigest[] = md5.digest();

for (int i = 0; i < messageDigest.length; i++) {
hexString.append(Integer.toHexString(0xFF & messageDigest));
}

hexString.toString();

JSONArray mainjson = JSONfunctions2.getJSONfromURL(loginURL + "?login=" + email +
"&password=" + password + "&sign=" + hexString.toString());
try {

String success = mainjson.getJSONObject(0).getString("status");
prefsmain2.edit().putString("SUCCESS", success).commit();

} catch (JSONException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(Void args) {

String suc = prefsmain2.getString("SUCCESS", "Default");
Toast.makeText(LoginActivity.this, suc + "", Toast.LENGTH_LONG).show();
}
}[/syntax]

Касательно JSONAdapter - соединение происходит через https - вполне возможно, что проблем в этом, тем не менее код класса:

[syntax=java5]public class JSONfunctions2 {

public static JSONArray getJSONfromURL(String url) {

InputStream is = null;
String result = "";
JSONArray jArray = null;
HttpsURLConnection con = null;

try {
URL url1 = new URL(url);
con = (HttpsURLConnection)url1.openConnection();

} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}

try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}

try {

jArray = new JSONArray(result);
} catch (JSONException e) {
Log.e("log_tag", "Error parsing data " + e.toString());
}

return jArray;
}
}[/syntax]

В ответ должен приходить JSON вида:

[syntax=php]{ "status": "success",
"message": "",
"session_id": "asdasddfcvxgdgfdfv",
"user":
[{ "company": "company",
"last_name": "last_name·",
"name": "name",
"middle_name": "middle_name",
"phone": "+1234567890",
"photo": "avatar.png" }] }[/syntax]

Но вместо этого приходит NPE в виде null:

Код: Выделить всё

Error converting result java.lang.NullPointerException
Error parsing data org.json.JSONException: End of input at character 0 of
Что делать и как быть? Ребята, помогайте.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Ошибка получения JSON через HTTPS

Сообщение altwin » 24 июн 2014, 23:38

время позднее и всеравно голова не соображает, но разве не нужно вызвать непостредственно метод connect() да и зачем отправлять запросы в основном потоке....?
просто для примера(там есть doInBackground):
[syntax=java]
public class Login extends Activity {
Button btnLogin;
Button Btnregister;
Button passreset;
EditText inputEmail;
EditText inputPassword;
private TextView loginErrorMsg;
/**
* Called when the activity is first created.
*/
private static String KEY_SUCCESS = "success";
private static String KEY_UID = "uid";
private static String KEY_USERNAME = "uname";
private static String KEY_FIRSTNAME = "fname";
private static String KEY_LASTNAME = "lname";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.pword);
Btnregister = (Button) findViewById(R.id.registerbtn);
btnLogin = (Button) findViewById(R.id.login);
passreset = (Button)findViewById(R.id.passres);
loginErrorMsg = (TextView) findViewById(R.id.loginErrorMsg);
passreset.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), PasswordReset.class);
startActivityForResult(myIntent, 0);
finish();
}});
Btnregister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), Register.class);
startActivityForResult(myIntent, 0);
finish();
}});
/**
* Login button click event
* A Toast is set to alert when the Email and Password field is empty
**/
btnLogin.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if ( ( !inputEmail.getText().toString().equals("")) && ( !inputPassword.getText().toString().equals("")) )
{
NetAsync(view);
}
else if ( ( !inputEmail.getText().toString().equals("")) )
{
Toast.makeText(getApplicationContext(),
"Password field empty", Toast.LENGTH_SHORT).show();
}
else if ( ( !inputPassword.getText().toString().equals("")) )
{
Toast.makeText(getApplicationContext(),
"Email field empty", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),
"Email and Password field are empty", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* Async Task to check whether internet connection is working.
**/
private class NetCheck extends AsyncTask
{
private ProgressDialog nDialog;
@Override
protected void onPreExecute(){
super.onPreExecute();
nDialog = new ProgressDialog(Login.this);
nDialog.setTitle("Checking Network");
nDialog.setMessage("Loading..");
nDialog.setIndeterminate(false);
nDialog.setCancelable(true);
nDialog.show();
}
@Override
protected Boolean doInBackground(String... args)
/**
* Gets current device state and checks for working internet connection by trying Google.
**/
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(3000);
urlc.connect();
if (urlc.getResponseCode() == 200) {
return true;
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
@Override
protected void onPostExecute(Boolean th){
if(th == true){
nDialog.dismiss();
new ProcessLogin().execute();
}
else{
nDialog.dismiss();
loginErrorMsg.setText("Error in Network Connection");
}
}
}
/**
* Async Task to get and send data to My Sql database through JSON respone.
**/
private class ProcessLogin extends AsyncTask {
private ProgressDialog pDialog;
String email,password;
@Override
protected void onPreExecute() {
super.onPreExecute();
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.pword);
email = inputEmail.getText().toString();
password = inputPassword.getText().toString();
pDialog = new ProgressDialog(Login.this);
pDialog.setTitle("Contacting Servers");
pDialog.setMessage("Logging in ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected JSONObject doInBackground(String... args) {
UserFunctions userFunction = new UserFunctions();
JSONObject json = userFunction.loginUser(email, password);
return json;
}
@Override
protected void onPostExecute(JSONObject json) {
try {
if (json.getString(KEY_SUCCESS) != null) {
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
pDialog.setMessage("Loading User Space");
pDialog.setTitle("Getting Data");
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
JSONObject json_user = json.getJSONObject("user");
/**
* Clear all previous data in SQlite database.
**/
UserFunctions logout = new UserFunctions();
logout.logoutUser(getApplicationContext());
db.addUser(json_user.getString(KEY_FIRSTNAME),json_user.getString(KEY_LASTNAME),json_user.getString(KEY_EMAIL),json_user.getString(KEY_USERNAME),json_user.getString(KEY_UID),json_user.getString(KEY_CREATED_AT));
/**
*If JSON array details are stored in SQlite it launches the User Panel.
**/
Intent upanel = new Intent(getApplicationContext(), Main.class);
upanel.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pDialog.dismiss();
startActivity(upanel);
/**
* Close Login Screen
**/
finish();
}else{
pDialog.dismiss();
loginErrorMsg.setText("Incorrect username/password");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void NetAsync(View view){
new NetCheck().execute();
}
}
[/syntax]
Изображение

ironz
Сообщения: 3
Зарегистрирован: 24 июн 2014, 22:58

Re: Ошибка получения JSON через HTTPS

Сообщение ironz » 24 июн 2014, 23:59

altwin писал(а):время позднее и всеравно голова не соображает, но разве не нужно вызвать непостредственно метод connect() да и зачем отправлять запросы в основном потоке....?
просто для примера(там есть doInBackground):
[syntax=java]
public class Login extends Activity {
Button btnLogin;
Button Btnregister;
Button passreset;
EditText inputEmail;
EditText inputPassword;
private TextView loginErrorMsg;
/**
* Called when the activity is first created.
*/
private static String KEY_SUCCESS = "success";
private static String KEY_UID = "uid";
private static String KEY_USERNAME = "uname";
private static String KEY_FIRSTNAME = "fname";
private static String KEY_LASTNAME = "lname";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.pword);
Btnregister = (Button) findViewById(R.id.registerbtn);
btnLogin = (Button) findViewById(R.id.login);
passreset = (Button)findViewById(R.id.passres);
loginErrorMsg = (TextView) findViewById(R.id.loginErrorMsg);
passreset.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), PasswordReset.class);
startActivityForResult(myIntent, 0);
finish();
}});
Btnregister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), Register.class);
startActivityForResult(myIntent, 0);
finish();
}});
/**
* Login button click event
* A Toast is set to alert when the Email and Password field is empty
**/
btnLogin.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if ( ( !inputEmail.getText().toString().equals("")) && ( !inputPassword.getText().toString().equals("")) )
{
NetAsync(view);
}
else if ( ( !inputEmail.getText().toString().equals("")) )
{
Toast.makeText(getApplicationContext(),
"Password field empty", Toast.LENGTH_SHORT).show();
}
else if ( ( !inputPassword.getText().toString().equals("")) )
{
Toast.makeText(getApplicationContext(),
"Email field empty", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),
"Email and Password field are empty", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* Async Task to check whether internet connection is working.
**/
private class NetCheck extends AsyncTask
{
private ProgressDialog nDialog;
@Override
protected void onPreExecute(){
super.onPreExecute();
nDialog = new ProgressDialog(Login.this);
nDialog.setTitle("Checking Network");
nDialog.setMessage("Loading..");
nDialog.setIndeterminate(false);
nDialog.setCancelable(true);
nDialog.show();
}
@Override
protected Boolean doInBackground(String... args)
/**
* Gets current device state and checks for working internet connection by trying Google.
**/
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(3000);
urlc.connect();
if (urlc.getResponseCode() == 200) {
return true;
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
@Override
protected void onPostExecute(Boolean th){
if(th == true){
nDialog.dismiss();
new ProcessLogin().execute();
}
else{
nDialog.dismiss();
loginErrorMsg.setText("Error in Network Connection");
}
}
}
/**
* Async Task to get and send data to My Sql database through JSON respone.
**/
private class ProcessLogin extends AsyncTask {
private ProgressDialog pDialog;
String email,password;
@Override
protected void onPreExecute() {
super.onPreExecute();
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.pword);
email = inputEmail.getText().toString();
password = inputPassword.getText().toString();
pDialog = new ProgressDialog(Login.this);
pDialog.setTitle("Contacting Servers");
pDialog.setMessage("Logging in ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected JSONObject doInBackground(String... args) {
UserFunctions userFunction = new UserFunctions();
JSONObject json = userFunction.loginUser(email, password);
return json;
}
@Override
protected void onPostExecute(JSONObject json) {
try {
if (json.getString(KEY_SUCCESS) != null) {
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
pDialog.setMessage("Loading User Space");
pDialog.setTitle("Getting Data");
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
JSONObject json_user = json.getJSONObject("user");
/**
* Clear all previous data in SQlite database.
**/
UserFunctions logout = new UserFunctions();
logout.logoutUser(getApplicationContext());
db.addUser(json_user.getString(KEY_FIRSTNAME),json_user.getString(KEY_LASTNAME),json_user.getString(KEY_EMAIL),json_user.getString(KEY_USERNAME),json_user.getString(KEY_UID),json_user.getString(KEY_CREATED_AT));
/**
*If JSON array details are stored in SQlite it launches the User Panel.
**/
Intent upanel = new Intent(getApplicationContext(), Main.class);
upanel.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pDialog.dismiss();
startActivity(upanel);
/**
* Close Login Screen
**/
finish();
}else{
pDialog.dismiss();
loginErrorMsg.setText("Incorrect username/password");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void NetAsync(View view){
new NetCheck().execute();
}
}
[/syntax]
что-то и я вас не пойму, причем тут метод метод connect()? Загвоздка не в проверке интернет соединения а в получении JSON

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Ошибка получения JSON через HTTPS

Сообщение altwin » 25 июн 2014, 00:17

ironz писал(а): что-то и я вас не пойму, причем тут метод метод connect()? Загвоздка не в проверке интернет соединения а в получении JSON
все может быть... я же говорю - спать уже пора, но ок, вторая попытка.
судя по тому, что строка con = (HttpsURLConnection)url1.openConnection(); находится в try, открыть соединение он не успевает или не может и в BufferedReader попадает значение присвоенное при инциализации, т.е. null,мне почему то кажется, что try там не нужен и должно быть примерно так(хотя странно как -то.... :) ):
[syntax=java5]
...
URL url1 = new URL(url);
HttpsURLConnection con = (HttpsURLConnection)url1.openConnection();

try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
...
[/syntax]
Ну и если честно я не пользовался HttpsUrlConnection классом, но судя по документации необходимо хотябы из keystore сертификат установить:
[syntax=java5]
KeyStore keyStore = ...;
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
tmf.init(keyStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

URL url = new URL("https://www.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
[/syntax]
хотя опять же, просто "вокруг" смотрю, я этой штукой не пользовался...

P.S. может volley + Gson ? И всетаки не делайте запросы в основном потоке... android этого не любит.
Изображение

ironz
Сообщения: 3
Зарегистрирован: 24 июн 2014, 22:58

Re: Ошибка получения JSON через HTTPS

Сообщение ironz » 25 июн 2014, 00:35

altwin писал(а):
ironz писал(а): что-то и я вас не пойму, причем тут метод метод connect()? Загвоздка не в проверке интернет соединения а в получении JSON
все может быть... я же говорю - спать уже пора, но ок, вторая попытка.
судя по тому, что строка con = (HttpsURLConnection)url1.openConnection(); находится в try, открыть соединение он не успевает или не может и в BufferedReader попадает значение присвоенное при инциализации, т.е. null,мне почему то кажется, что try там не нужен и должно быть примерно так(хотя странно как -то.... :) ):
[syntax=java5]
...
URL url1 = new URL(url);
HttpsURLConnection con = (HttpsURLConnection)url1.openConnection();

try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
...
[/syntax]
Ну и если честно я не пользовался HttpsUrlConnection классом, но судя по документации необходимо хотябы из keystore сертификат установить:
[syntax=java5]
KeyStore keyStore = ...;
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
tmf.init(keyStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

URL url = new URL("https://www.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
[/syntax]
хотя опять же, просто "вокруг" смотрю, я этой штукой не пользовался...

P.S. может volley + Gson ? И всетаки не делайте запросы в основном потоке... android этого не любит.
Если честно, я уже почти расколупал весь JSON с помощью Volley, но мне очень хочется понять как оно работает, библиотеки это хорошо - но хочется углубиться. Сейчас попробую поработать с сертификатами.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Ошибка получения JSON через HTTPS

Сообщение altwin » 25 июн 2014, 09:41

ironz писал(а):
Если честно, я уже почти расколупал весь JSON с помощью Volley, но мне очень хочется понять как оно работает, библиотеки это хорошо - но хочется углубиться. Сейчас попробую поработать с сертификатами.
Вот никогда я этого не понимал... ну вот что вы поймете используя урезанный функционал стандартного api вместо "швейцарского ножа"? Вам так интересно как это делать стандартными средствами? а зачем? Если хочется разобраться, то вам как минимум нужно реализовывать весь http клиент самостоятельно ровно как и jsonobject, а для того, чтобы понять действительно качественно придется на ассембелере это все писать. оно вам надо? :) В этом и особенность java -вам не нужно знать как оно работает... 80% программистов по сути -пользователи. Для того и придумали абстракцию и инкапсуляцию собственно как и ООП в целом.
Изображение

Аватара пользователя
hondrus
Сообщения: 1
Зарегистрирован: 02 июл 2014, 19:15
Откуда: Астана, Казахстан
Контактная информация:

Re: Ошибка получения JSON через HTTPS

Сообщение hondrus » 08 июл 2014, 13:09

altwin писал(а): Вот никогда я этого не понимал... ну вот что вы поймете используя урезанный функционал стандартного api вместо "швейцарского ножа"? Вам так интересно как это делать стандартными средствами? а зачем? Если хочется разобраться, то вам как минимум нужно...
Т.е. вы предлагаете отказаться от стандартных инструментов по типу HTTPUrlConnection и использовать библиотеки(Volley, Android Asynchronous Http Client)?

Ответить