Error with latest jar of Nanohttpd - java

I followed the SO for setting NanoHttpd to serve files from here - How to serve a mp3 file using latest NanoHTTPD 2.3.0 in Android?
This works but I require the use the latest version from Github, because it handles more HTTP methods and is required for project.
I built the jar locally and added and compiled the APK. The web server initializes but every request is returned as Not Found. Nothing else. There is no log for that as well to see the problem. What is going on?
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Map;
import android.util.Log;
import org.nanohttpd.protocols.http.NanoHTTPD;
import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;
import org.nanohttpd.protocols.http.request.Method;
import static org.nanohttpd.protocols.http.response.Response.newChunkedResponse;
public class MainActivity extends AppCompatActivity {
public StackOverflowMp3Server server;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
server = new StackOverflowMp3Server();
try {
server.start();
} catch(IOException ioe) {
Log.w("Httpd", "The server could not start.");
}
Log.w("Httpd", "Web server initialized.");
}
#Override
public void onDestroy()
{
super.onDestroy();
if (server != null)
server.stop();
}
public class StackOverflowMp3Server extends NanoHTTPD {
public StackOverflowMp3Server() {
super(8089);
}
public Response serve(String uri, Method method,
Map<String, String> header, Map<String, String> parameters,
Map<String, String> files) {
String answer = "";
Log.w("HTTPD", uri);
Log.w("HTTPD", parameters.toString());
Log.w("HTTPD", "Method is: "+method.toString());
Log.w("HTTPD", "Header is: "+header.toString());
FileInputStream fis = null;
try {
fis = new FileInputStream("/storage/C67A-18F7/"
+ "/Music/"+uri);
Log.w("HTTPD", uri + " found");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return newChunkedResponse(Status.OK, "audio/mpeg", fis);
}
}
}
This same code works in 2.2 till 2.3
But not in the latest, 2.3.2
I get the server started prompt in the adb logcat
03-26 18:18:26.005 15056 15056 W Httpd : Web server initialized.
But all other requests returns Not Found
>$ curl -X GET http://192.168.1.2:8089
Not Found
>$ curl -X GET http://192.168.1.2:8089/demo.mp3
Not Found
I can't find what the problem is with the code?

Your serve() does not override any method NanoHTTPD is calling. The default implementation returns "404 Not Found".
The signature for serve() is
protected Response serve(IHTTPSession session)
However it's deprecated. Have a look at IHandlers as introduced in this commit. (The default handler does still call the deprecated serve() method.)

Related

Use Infura to run a IPFS node in Java Android

I am trying to connect to an Infura node from Java Android application.
I was following these documents to connect to an infura node.
https://kauri.io/managing-storage-in-a-java-application-with-ipfs/3e8494f4f56f48c4bb77f1f925c6d926/a
https://github.com/ipfs-shipyard/java-ipfs-http-client/issues/115
Code:
package com.example.javahttp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import io.ipfs.api.IPFS;
public class MainActivity extends AppCompatActivity {
IPFS ipfs ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask().execute();
}
private class MyTask extends AsyncTask<Void , Void, Void > {
#Override
protected Void doInBackground(Void... voids) {
IPFS ipfs = new IPFS("/dnsaddr/ipfs.infura.io/tcp/5001/https");
try{
System.out.println("connected");
System.out.println("id: "+ ipfs.id());
}catch(Exception e){
System.out.println("not connected"+e);
}
return null;
}
}
}
I am getting this error.
java.lang.RuntimeException: IOException contacting IPFS daemon.
Trailer: null ipfs method not allowed
Any suggestions please.
I don't get why there is such an error but when I used a plain java class to connect with it. It was possible ,you may refer here to my repository blockchain with java to see if you have all the relevant dependencies and you have been doing it properly because I am not familiar with android but I am familiar with web3j.
You can use the below code to connect with an infura node and parse a file to it.
import io.ipfs.api.IPFS;
import io.ipfs.api.MerkleNode;
import io.ipfs.api.NamedStreamable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class App {
public static void main(String[] args) throws IOException {
IPFS ipfs = new IPFS("/dnsaddr/ipfs.infura.io/tcp/5001/https");
try {
NamedStreamable.InputStreamWrapper is = new NamedStreamable.InputStreamWrapper(new FileInputStream());
MerkleNode response = ipfs.add(is).get(0);
} catch (IOException ex) {
throw new RuntimeException("Error whilst communicating with the IPFS node", ex);
}
}
}
In case anyone has trouble with this nowadays, the fix to this issue was simply to upgrade to the newest version.
I upgraded from v1.2.3 to v1.3.3 and the issue disappeared.
For maven, pom.xml:
<dependency>
<groupId>com.github.ipfs</groupId>
<artifactId>java-ipfs-http-client</artifactId>
<version>v1.3.3</version>
</dependency>

Carrying and reusing information (json string) from an AsyncTask?

I have created a simple android app with 3 TextViews and then run an AsyncTask Task via a different class the next step would be to carry the information over and make the task reusable.
The Task will consume a String (URL) and the context of the MainActivity.
The Task will make a simple REST Request (GET) and retrieve a json string.
I have then created another class that which gets the json response and creates a .json file saves it to
..../0/Notes/launch.json
The folder "Notes is created by myself via file.mkdirs().
In the MainActivity I created an InputStream to read the .json file saved by the AsyncTask but once I try to open it, it gives me a FileNotFoundException.
Here's the code of my MainActivity.class
package com.example.root.example;
import android.Manifest;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200);
String url = "https://api.spacexdata.com/v3/launches/upcoming"; //Copy the url and open it in your browser to see the json.
AsyncCall asyncCall = new AsyncCall(getApplicationContext());
asyncCall.myAsyncTask(url);
try {
InputStream inputStream = this.getAssets().open("launch.json");
int size = inputStream.available();
byte[] buffer = new byte[size];
inputStream.read(buffer);
inputStream.close();
String jsonStringFromFile= new String(buffer,"UTF-8");
JSONObject launchObject = new JSONObject(jsonStringFromFile);
System.out.println(launchObject.get("flight_number"));
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
This is the AsyncCall.class (making and retrieving the json etc..)
package com.example.root.example;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class AsyncCall {
FileCreator fileCreator = new FileCreator();
private final Context myContext;
public AsyncCall(final Context context) {
myContext = context;
}
public void myAsyncTask(final String url) {
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
fileCreator.generateFile(myContext, myContext.getString(R.string.fileName), response.body().string());
} catch (IOException ioe) {
ioe.getMessage();
}
return null;
}
}.execute();
}
}
what am I trying to archive? I'm trying to save information (json here) and make it reusable just as the Falcon 9.
The issue lies in carrying information over to a different class.
If there's an alternative solution (other than saving a .json file) to fix this issue then please don't hesitate to post it.
This is just my first issue, the second issue appears once you open the api link and see that there are a few more than just one JSON String (0,1,2,3,4... upcoming missions).
I have no clue in any way to tacle the first let alone the second problem and have started over a few times, a while ago multiple times.
Within your Activity, you can get the JSON like so
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, final Response response) throws IOException {
try {
final String responseData = response.body().string();
JSONObject json = new JSONObject(responseData);
String flightNumber = json.getString("flight_number");
// TODO: Load number into a TextView
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Looking at your API response, though, you'll actually need new JSONArray(responseData), and you would have to loop over that to get each individual object's flight number

How to make MongoDB Service Available?

I am developing OSGi Mongodb bundle I have also added the following dependencies
com.mongodb
org.apache.felix.fileinstal
org.amdatu.mongo
org.apache.felix.configadmin
and all the dependency managers but in gogo console I get the following error message
org.amdatu.mongo
org.osgi.service.cm.ManagedServiceFactory(service.pid=org.amdatu.mongo) registered
org.osgi.service.log.LogService service optional unavailable
[11] agenda.mongodb.mongo_gfs
agenda.mongo.inter.AgendaMongo() unregistered
org.amdatu.mongo.MongoDBService service required unavailable
the main problem is MongoDBService is not available I must require this service for solving this problem I have read the book according to them
From a development perspective, everything seems fine, but when you
run the appliā€ cation, it will complain that the MongoDBService is
unavailable. You can figure this out with the dmcommand in the shell.
We did however set up MongoDB on our system and deployed the necessary
dependencies in our runtime. Still, the MongoDBService was unable to
start. How come? This is because the MongoDBService needs some
mandatory configuration in order to know to what database to connect
to. The Amdatu MongoDB Serviceuses the Managed Service Factory pattern
(see Chapter 4), and in order to bootstrap it, we need to supply a
configuration file. In order to supply the configuration file, we need
to create a new folder in our agendaproject. Create a new folder
called load. This is the default name that the runtime will look for
in order to spot configuration files. Next, add an empty text file and
call it something like org.amdatu.mongo-demo.xml. The configuration
file needs at least the following information: dbName=demo
I have also apply this but its still unavailable.
This is interface:
package agenda.mongo.inter;
import java.io.InputStream;
public interface AgendaMongo {
public String store_in_db();
public InputStream getData(Object file_id);
}
This is the implementation for Mongodb:
package agenda.mongodb.gridfs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import org.amdatu.mongo.MongoDBService;
import org.bson.types.ObjectId;
import agenda.mongo.inter.AgendaMongo;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;
public class Gridfs_Mongodb implements AgendaMongo{
GridFSInputFile gfsinput=null;
private volatile MongoDBService mongoservice;
public String store_in_db() {
/*try {
GridFS gfsHandler;
gfsHandler = new GridFS(mongoservice.getDB(), "rest_data");// database
File uri = new File("f:\\get1.jpg"); // name and
gfsinput = gfsHandler.createFile(uri);
gfsinput.saveChunks(1000);
gfsinput.setFilename("new file");
gfsinput.save();
//System.out.println(gfsinput.getId());
//save_filepath("file",gfsinput.getId());
Object get_id = gfsinput.getId();//get_filename();
//System.out.println(getData(get_id));
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
//System.out.println("Exception");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
//System.out.println("Exception");
e.printStackTrace();
}*/
System.out.println("DB:" + mongoservice.getDB());
return mongoservice.getDB()+"";
}
/*
* Retrieving the file
*/
public InputStream getData(Object file_id) {
GridFS gfsPhoto = new GridFS(mongoservice.getDB(), "rest_data");
GridFSDBFile dataOutput = gfsPhoto.findOne((ObjectId) file_id);
DBCursor cursor = gfsPhoto.getFileList();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
System.out.println(dataOutput);
return dataOutput.getInputStream();
}
void start(){
System.out.println("hello");
System.out.println(store_in_db());
}
}
Here I was just trying to get database name because every thing can be done after that but I t was returning me NULL because MongoDBService is Unavailable.
At this is Activator class
package agenda.mongodb.gridfs;
import org.amdatu.mongo.MongoDBService;
import org.apache.felix.dm.DependencyActivatorBase;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.BundleContext;
import agenda.mongo.inter.AgendaMongo;
public class Activator extends DependencyActivatorBase {
#Override
public void init(BundleContext arg0, DependencyManager manager)
throws Exception {
manager.add(createComponent()
.setInterface(AgendaMongo.class.getName(), null)
.setImplementation(Gridfs_Mongodb.class)
.add(createServiceDependency()
.setService(MongoDBService.class)
.setRequired(true)));
}
#Override
public void destroy(BundleContext arg0, DependencyManager arg1)
throws Exception {
// TODO Auto-generated method stub
}
}
The Interface package is an exported package and the implementation package is private.
The configuration file should have a .cfg extension (not .xml).

Using JAVA RMI in Android application

I've read lots of threads about this issue, and i couldnt see a 'real' solution for it.
I made a java project - which is a rmi server and i have an android application which suppose to be also a rmi client.
When i checked if the server works I wasn't wise enough to test the client on an android project and i made a test client on a simple java project.
Now when i'm trying to connect my android application to server i fail because the android project doesn't recognize the java rmi package.
Why that happen? what should I do?
You can also use the following library LipeRMI
Here is an example of a Android client interacting with Java Server via LipeRMI.
Create the Following 2 classes and a interface for Java application.
//TestService.java
package test.common;
public interface TestService {
public String getResponse(String data);
}
//TestServer.java
import java.io.IOException;
import java.net.Socket;
import test.common.TestService;
import lipermi.exception.LipeRMIException;
import lipermi.handler.CallHandler;
import lipermi.net.IServerListener;
import lipermi.net.Server;
public class TestServer implements TestService {
public TestServer() {
try {
CallHandler callHandler = new CallHandler();
callHandler.registerGlobal(TestService.class, this);
Server server = new Server();
server.bind(7777, callHandler);
server.addServerListener(new IServerListener() {
#Override
public void clientDisconnected(Socket socket) {
System.out.println("Client Disconnected: " + socket.getInetAddress());
}
#Override
public void clientConnected(Socket socket) {
System.out.println("Client Connected: " + socket.getInetAddress());
}
});
System.out.println("Server Listening");
} catch (LipeRMIException | IOException e) {
e.printStackTrace();
}
}
#Override
public String getResponse(String data) {
System.out.println("getResponse called");
return "Your data: " + data;
}
}
//TestMain.java
public class TestMain {
public static void main(String[] args) {
TestServer testServer = new TestServer();
}
}
Android client:
//MainActivity.java
package com.example.lipermidemoandroidclient;
import java.io.IOException;
import test.common.TestService;
import lipermi.handler.CallHandler;
import lipermi.net.Client;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private String serverIP = "192.168.1.231";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnGet = (Button) findViewById(R.id.btnGet);
btnGet.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
new Conn().execute();
}
});
}
class Conn extends AsyncTask<Void, Void, MainActivity> {
#Override
protected MainActivity doInBackground(Void... params) {
Looper.prepare();
try {
CallHandler callHandler = new CallHandler();
Client client = new Client(serverIP, 7777, callHandler);
TestService testService = (TestService) client.getGlobal(TestService.class);
String msg = testService.getResponse("qwe");
//Toast.makeText(MainActivity.this, testService.getResponse("abc"), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
Looper.loop();
return null;
}
}
}
//TestService.java
package test.common;
public interface TestService {
public String getResponse(String data);
}
Add the LipeRMI library to both the projects
Make sure you add INTERNET permission in Android project
Also make sure you have the TestService.java file placed in same package name at both places for eg. test.common package here
Also change value of serverIP variable in Android MainActivity.java to the IP of the machine running the Java code.
I had the same problem and changed my communication to socket communication!
As far as I could figure out Java.rmi unfortunately does not come with Android and therefore it's not possible to use it.
However there are some more disucssions in this post.
Android doesn't support RMI. You should change to socket or raw TCP communication.

Android Simple HTTP Request?

I have this code for an Android application I'm trying to create into interact with my PHP website. I have the android.permission.INTERNET permission activated and it keeps creating a toast that says "ERROR." instead of the contents of the website. Here is my only java file:
package com.http.request;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class HttprequestActivity extends Activity {
/** Called when the activity is first created. */
private String doHTTPRequest(String url){
String results = "ERROR";
try
{
HttpClient hc = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
HttpResponse rp = hc.execute(post);
if(rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
results = EntityUtils.toString(rp.getEntity());
}
}catch(IOException e){
e.printStackTrace();
}
return results;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String results = doHTTPRequest("http://www.yahoo.com");
Toast.makeText(getApplicationContext(), results, Toast.LENGTH_LONG).show();
}
}
I would check to make sure that,
If there is an exception being thrown, investigate what is causing the IOException
Your server could potentially be returning a non-200 response code.
Put in some breakpoints and see whats happening there. My bet is on the response code.
That is your own "ERROR" string which the Toast() displays. Better change
catch(IOException e){
e.printStackTrace();
}
to
catch(IOException e){
result = "ERROR IOException";
e.printStackTrace();
}
The exception is thrown as you try to connect in the main thread which is not permitted. Put doHTTPRequest() in a thread or AsyncTask.
What is your stacktrace says, LogCat? What is the error? Add more info, make it more clear to understand than "guessing of coffee beans"
My guess is: this happens because you are trying to do network operation in UI thread which is not allowed in 3.0+ versions.
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

Categories