android, Force Close in a NanoHTTPD project - android

I'm implementing a custom web server by using NanoHTTPD.
I have BaseServer class that extends NanoHTTPD:
public class BaseServer extends NanoHTTPD {
public BaseServer(int port) {
super(port);
// TODO Auto-generated constructor stub
}
#Override
public Response serve(String uri, Method method,
Map<String, String> header, Map<String, String> parms,
Map<String, String> files) {
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<head><title>Debug Server</title></head>");
sb.append("<body>");
sb.append("<h1>Response</h1>");
sb.append("<p><blockquote><b>URI -</b> ").append(uri).append("<br />");
sb.append("<b>Method -</b> ").append(method)
.append("</blockquote></p>");
sb.append("<h3>Headers</h3><p><blockquote>").append(header)
.append("</blockquote></p>");
sb.append("<h3>Parms</h3><p><blockquote>").append(parms)
.append("</blockquote></p>");
sb.append("<h3>Files</h3><p><blockquote>").append(files)
.append("</blockquote></p>");
sb.append("</body>");
sb.append("</html>");
return new Response(sb.toString());
}
}
and an activity that use this class by this code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
bs.start();
Toast.makeText(this, "Server Started", 1).show();
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(this, e.getMessage(), 3).show();
}
}
My server start correctly, but when I send a request from my browser, I have force close in my app !
when below code was executed(it is in try block), pointer go to final block!!! (Not cache) and I send a Force Close to my phone !!
ByteBuffer fbuf = f.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f.length());
f is null (no file sent!) and this code should handle this condition !, dosn't it?!

When you run on Android, and write temp files, you need to add a permission to your application. Without the permission, opening the file will throw an exception and bad things will result. Off the top of my head, I think the permission you need to add to your AndroidManifest.xml is
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Try it and see!

From your code, and without the stacktrace, several possibilities :
bs is null
bs.start() is a blocking operation, so you can't call it in the ui thread.
you lack a permission to listen on a restricted port.

Related

Windows Azure Service Client

I'm trying the my Azure Mobile Service. Below is the code to make a new ToDo item entry. The sample Android code shows how to create a mobile client. I added it to the onCreate method as mentioned in the example.
But the insert always fails. I always get an exception which says com.microsoft.windowsazure.mobileservices.MobileServiceException: Error while processing request.
mClient does get initialized. But, mClient.mCurrentUser is null. Not sure if this is a problem.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
mClient = new MobileServiceClient("https://myservice.azure-mobile.net/",
"slkerjasfi234eSomePrivateKey", this);
Item item = new Item();
item.setText("Awesome item");
item.setComplete(false);
mClient.getTable(Item.class).insert(item,
new TableOperationCallback<Item>() {
public void onCompleted(Item entity,
Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
ShowMessage("Success");
} else {
ShowMessage("Failed");
}
}
});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In my case, it looked like the key (parameter 2 in MobileServiceClient constructor) was incorrect. That is how I had downloaded it though. It happened again today and I manually fixed the key and it worked for another service. Believe it was the same issue here. To view your key, you go to your service in Azure and click Manage Keys at the bottom.

Android not waiting for DB response before finishing statement

I have an interesting problem that I've never run into in programming before. I have an onClickListener that does a lot of username and password checks (makes sure the username is proper length, not taken, etc). I'm using MobDB, and I was using a conditional statement that would return a row if the username already existed. The problem is that the Listener skips the DB and goes to the final check that, if everything works, posts a new username and password to my DB. How can I make it wait for a response from the DB before skipping to the last check?
Here is the relevant code:
usernamecheck3 = true;
MobDB.getInstance().execute(APP_KEY, null, rd, null, false, new MobDBResponseListener() {
#Override public void mobDBSuccessResponse() {
usernamecheck3 = false;
Log.e("mobdbSuccess:", "success");
}
#Override public void mobDBResponse(Vector<HashMap<String, Object[]>> row) {
}
#Override public void mobDBResponse(String jsonObj) {
/*Log.e("mobdbSuccess:", "jsonObj");
Log.e("mobdbSuccess:", jsonObj);
JSONObject mainObject;
try {
mainObject = new JSONObject(jsonObj);
// need to parse the json object.
} catch (JSONException e1) {
e1.printStackTrace();
} */
}
#Override public void mobDBFileResponse(String fileName, byte[] fileData) {
//get file name with extension and file byte array
}
#Override public void mobDBErrorResponse(Integer errValue, String errMsg) {
usernamecheck3 = false;
Log.e("doesnt", "work");
}
});
if(usernamecheck3 == false){
Toast.makeText(getApplicationContext(), "Username is taken, please choose another", Toast.LENGTH_SHORT).show();
}
Basically the check always returns true, and then logcat will say mobdbSuccess: success, which should have set the Bool to false.
Thanks.
MobDBResponseListener is executing on a different thread. What happens here is that the processing is split, while a thread is doing the query, the main thread on which you added the listener, skips right ahead to the validation. Your best bet is to place the validation inside the MobDBResponseListener, on the mobDBResponse method.
Try to debug your code and calls, the Listener may be using an async task. If so, you may do anything you please from the response method, as it will be executing in the main thread again. Otherwise, you should look at solutions that handle threaded execution like Handlers

Android nanohttpd doesn't start properly

I need httpd server in my app, so I've choose NanoHttpd.
I've subclassed my own server:
public class StreamingServer extends NanoHTTPD {
private Context mContext;
public StreamingServer(Context context) {
super(8080);
mContext = context;
Log.i("MyServer", "Streaming server created");
}
And I'm trying to launch my server in main activity:
// onCreate:
server = new StreamingServer(getApplicationContext());
Here is my onResume method:
// onResume:
super.onResume();
try {
server.start();
} catch (IOException e) {
Log.i(TAG, "exception!");
e.printStackTrace();
}
Log.i(TAG, "started!");
and onPause:
super.onPause();
if (server != null) {
server.stop();
Log.i(TAG, "stopped!");
}
I've also done proper setup:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
So I believe I've done everything right. But launching my app leads to nothing (Page are unavailable). Some how 2 or 3 launches leads to server launch (and I do NOTHING different at that moment).
What I'm doing wrong?
NanoHttpd expects you to override the "serve()" method. The response object that you return from your overridden method will be returned to the web browser that hits your server. The "README" document on the github site has a fully functioning example (https://github.com/NanoHttpd/nanohttpd) that returns debug information to the browser.
If you want to serve more interesting content, look at the samples/ folder inside the NanoHttpd project, or the webserver/ folder for a fully functional web server.

android: how to make sure i posted correctly using httppost

I have a web address www.abc.com/check ... I have created a web service on this address for receiving data. Through an android app i send some data to this address using following code:
public class TestappActivity extends Activity {
EditText ch;
Button btn;
InputStream is;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ch=(EditText)findViewById(R.id.ch);
btn=(Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
sendData();
}
});
}
private void sendData() {
Log.i(getClass().getSimpleName(), "send task - start");
HttpParams p=new BasicHttpParams();
p.setParameter("name", ch.getText());
HttpClient client = new DefaultHttpClient(p);
try {
HttpResponse response=client.execute(new HttpPost("http://www.abc.com/check"));
is=response.getEntity().getContent();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i(getClass().getSimpleName(), "send task - end");
}
}
How can i find if my post was successful ? What do i get back when i post something. ?
[update]Simple solution, you can just check the status code
response.getStatusLine().getStatusCode();
It's a integer(200 means OK, 500 means error on server) , Reference Here
Or a completely check by using the response body
response.getEntity().getContent();
It is generated on the server by your service, so if you want to assure the invocation is really successful, you can return something to client. e.g. a XML string
"<status>OK</status>"
in the response body would be enough. You will get it on client and then do whatever you want to do.
I recommend the simpler solution. Thanks shraddha
I guess baoz is right, but there is one simple alternative to this.
response.getStatusLine.getstatuscode(); //200-successful
It will return numeric response code for success as well as error. Moreover, if the response is negative, it will return you relevant error code so that you can track and catch those errors.
Regards.

Android - result from AsyncTask not being returned to main Activity

I'm trying to use an AsyncTask-extended class to handle connecting to a URL, parsing JSON, displaying an indeterminate ProgressDialog during parsing, and returning the results as key-value pairs in a HashMap to the main Activity. The results of the HashMap will then be read by the main Activity and put into form fields. However, even though I'm populating the HashMap in my AsyncTask (evidenced by println statements), calling a method in the main Activity that returns the HashMap yields an empty result. I can't figure out if this is something I'm doing wrong, or if I'm misunderstanding the capabilities of AsyncTask.
I'm debating converting my class that extends AsyncTask to an Activity. Essentially, the user should not be able to do anything else during this data search/parsing and should wait until the ProgressDialog goes away before they can interact with the application again (or by hitting the back button). Also, my application needs to be able to handle certain cases in my AsyncTask where exceptions are caught (can't connect to URL, bad JSON, product ID to search by cannot be found) and custom error dialogs are tailored for those exceptions. I could easily do this if this class were an Activity, as I could send back different result codes when calling finish(), depending on if an exception is caught.
Again, I'm not sure if AsyncTask is the best solution here, since the user will not be doing anything else while the information is being gathered and parsed. Please advise me if a new Activity would make sense or if I'm just mangling my implementation of a background thread.
MainActivity.java
mInitiateProductLookupButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ProductLookup pl = new ProductLookup(id, MainActivity.this);
pl.execute();
// The below variable is always empty!
HashMap<String, String> productInfo = pl.getProductInfo();
applyProductInfoToFormFields(productInfo);
}
});
ProductLookup.java
public class ProductLookup extends AsyncTask<Object, Void, HashMap<String, String>> {
private String mProductID;
private Context mContext;
HashMap<String, String> mProductInfo;
ProgressDialog mDialog;
public ProductLookup(String id, Context applicationContext) {
mProductID = id;
mContext = applicationContext;
mProductInfo = new HashMap<String, String>();
}
#Override
protected void onPreExecute() {
mDialog = new ProgressDialog(mContext);
mDialog.setMessage("Loading product info. Please wait...");
mDialog.setIndeterminate(true);
mDialog.setCancelable(false);
mDialog.show();
}
#Override
protected void onPostExecute(HashMap<String, String> result){
super.onPostExecute(result);
mDialog.dismiss();
mProductInfo = result;
}
#Override
protected HashMap<String, String> doInBackground(Object... params) {
try {
// Connect to URL, parse JSON, and add key-value pairs to mProductInfo...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
finally {
try {
// Close input/output reader variables
} catch (IOException e) {
e.printStackTrace();
}
}
return mProductInfo;
}
public HashMap<String, String> getProductInfo(){
return this.mProductInfo;
}
}
When you issue .execute() that runs as threaded and doesn't wait for the result.
So whatever you call after this it, is empty as the data has not been loaded yet.
You need to set on PostExecuted the result directly to your Activity via a setter MainActivity.this.setProductInfo(result)
There is some miss concept for you. The statement after AsyncTask.execute() will be executed just after the call. While your doInBackground is performing in other thread. Here, when you are using productInfo map, the doInBackground was not completed so result is not populated there
Easy solution for you is to use the result in the onPostExecute methord.
protected void onPostExecute(HashMap<String, String> result){
mDialog.dismiss();
mProductInfo = result;
applyProductInfoToFormFields(productInfo);
}

Categories

Resources