Reputation: 2226
I am starting to learn to develop an android app (hopefully I can understand this awesome technology).
I have a Rest API that I build myself with PHP.
The case is, the android app scan a QR-Code and then send the resultScan to my Rest API.
Here is my code:
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.zxing.Result;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
import org.json.JSONObject;
public class InfoCoilActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
private static final int REQUEST_CAMERA = 1;
private ZXingScannerView scannerView;
private String responseResult;
@Override
public void handleResult(Result result) {
final String scanResult = result.getText();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Result Scan For Info Coil");
builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
scannerView.resumeCameraPreview(InfoCoilActivity.this);
}
});
builder.setMessage("Result " + handleRequestApi(scanResult));
AlertDialog alert = builder.create();
alert.show();
}
public String handleRequestApi(String textCode) {
String URL = "http://my-web.com/api/morowali-coil/" + textCode;
final RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
responseResult = response.toString();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
responseResult = error.toString();
}
}
);
requestQueue.add(jsonObjectRequest);
return responseResult;
}
}
Please see in builder.setMessage("Result " + handleRequestApi(scanResult));
When I scan the qr code in first shot, I got message
Result null
I try to see in logcat, in the first shot, successfully get the response json like this:
10-17 14:07:01.492 11568-11568/com.dzil.myapplication E/Rest Response:: {"id":889,"coil_number":"QLZ18K01014A","planning_delivery":"WAREHOUSE","billet_number":"Y180908B03-4","width":0,"thickness":"0.00","grade":"S30403","size":"1.84*1250*C","actual_size":"1.85*1249","quantity":1,"nett":20930,"gross":21016,"customer":"IIS","contract_number":"IRNC18\/CC1137","procurement_contract_number":"","white_roll_number":"N1809100738","production_date":"2018-09-21","standard_eksekutif":"EN 10028-7","order_number":"ET18\/CC708001-IIS","unstuffing_plan":"2018-10-14","length":1143,"production_warehouse":"6#库","port":"Surabaya","vessel":null,"vessel_id":2,"urut":889,"lokasi":null,"lokasi_terakhir":null,"nama_file":"Copy of morowali-surabaya-example-format-data","created_by":"1","updated_by":"1","created_at":"2018-10-12 16:09:46","updated_at":"2018-10-12 16:09:46"}
But when I try again in second shot, it normal that I got those json like json above
Result {"id":889,"coil_number":"QLZ18K01014A","planning_delivery":"WAREHOUSE","billet_number":"Y180908B03-4","width":0,"thickness":"0.00","grade":"S30403","size":"1.84*1250*C","actual_size":"1.85*1249","quantity":1,"nett":20930,"gross":21016,"customer":"IIS","contract_number":"IRNC18\/CC1137","procurement_contract_number":"","white_roll_number":"N1809100738","production_date":"2018-09-21","standard_eksekutif":"EN 10028-7","order_number":"ET18\/CC708001-IIS","unstuffing_plan":"2018-10-14","length":1143,"production_warehouse":"6#库","port":"Surabaya","vessel":null,"vessel_id":2,"urut":889,"lokasi":null,"lokasi_terakhir":null,"nama_file":"Copy of morowali-surabaya-example-format-data","created_by":"1","updated_by":"1","created_at":"2018-10-12 16:09:46","updated_at":"2018-10-12 16:09:46"}
Please advice!
Upvotes: 0
Views: 554
Reputation: 332
This error is because of asynchronisity in using volley and alert dialog. You can create a custom interface like below code:
public interface VolleyResponseListener{
void onVolleyResponse(String response);
}
and use it in your codes.
public class InfoCoilActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler, VolleyResponseListener {
private static final int REQUEST_CAMERA = 1;
private ZXingScannerView scannerView;
private String responseResult;
private VolleyResponseListener volleyResponseListener;
public interface VolleyResponseListener{
void onVolleyResponse(String response);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
volleyResponseListener = (VolleyResponseListener) this;
//... your codes...
}
@Override
public void handleResult(Result result) {
handleRequestApi(result.getText());
}
public void handleRequestApi(String textCode) {
String URL = "http://my-web.com/api/morowali-coil/" + textCode;
final RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
volleyResponseListener.onVolleyResponse(response.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
volleyResponseListener.onVolleyResponse(error.toString());
}
}
);
requestQueue.add(jsonObjectRequest);
}
@Override
public void onVolleyResponse(String response){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Result Scan For Info Coil");
builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
scannerView.resumeCameraPreview(InfoCoilActivity.this);
}
});
builder.setMessage("Result " + response);
AlertDialog alert = builder.create();
alert.show();
}
}
Notice: I've add and remove some codes. Be carefull about implements
and onCreate
.
Upvotes: 0
Reputation: 3894
Your dialog was created immediately without waiting for the response because the function handleRequestApi(scanResult)
was called asynchronously, therefore it showed null instead because the initial value of responseResult
in your activity was null at the time.
To fix this, you should create the dialog only when it receives the response:
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle(...)
.setPositiveButton(...)
.setMessage(response.toString())
.create();
dialog.show();
}
}, ...
Upvotes: 1
Reputation: 4007
You can't do it like this because of asynchronism. The first shot returns null because the handleRequestApi()
method does not have the response of the request. The second shot returns something because of cache.
To use asynchronism correctly, you have to manage your response directly in the
onResponse()
callback. You want to display an AlertDialog ? Do something like this
@Override
public void onResponse(JSONObject response) {
responseResult = response.toString();
AlertDialog.Builder builder = new AlertDialog.Builder(InfoCoilActivity .this);
builder.setTitle("Result Scan For Info Coil");
builder.setPositiveButton("Continue", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialogInterface, int i) {
scannerView.resumeCameraPreview(InfoCoilActivity.this);
}
});
builder.setMessage("Result " + response);
AlertDialog alert = builder.create();
alert.show();
}
Upvotes: 2
Reputation: 28229
handleRequestApi
is an asynchronous method, meaning that it returns before getting any value from your API.
So return responseResult
will always return the initial value of null.
see: Asynchronous vs synchronous execution, what does it really mean? for more information about asynchronous tasks
Upvotes: 2