web-dev-qa-db-fra.com

Utilisation de NanoHTTPD dans Android

J'essaie d'utiliser NanoHTTP pour servir un fichier HTML. Cependant, NanoHTTP est relativement non documenté, et je suis nouveau sur Android. Ma question est, où puis-je stocker le fichier html, et comment puis-je le servir spécifiquement en utilisant NanoHTTP.

28
Zwade

Une réponse tardive mais peut être utile aux autres.

Voici un simple serveur Web bonjour, pas exactement ce que vous demandez, mais vous pouvez continuer à partir d'ici. Le programme suivant suppose que vous avez un répertoire www à la racine de la carte SD et un fichier index.html à l'intérieur.

Activité principale Httpd.Java:

package com.inforscience.web;

import Android.app.Activity;
import Android.os.Bundle;
import Android.os.Environment;
import Android.util.Log;
import Java.io.*;
import Java.util.*;


public class Httpd extends Activity
{
    private WebServer server;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        server = new WebServer();
        try {
            server.start();
        } catch(IOException ioe) {
            Log.w("Httpd", "The server could not start.");
        }
        Log.w("Httpd", "Web server initialized.");
    }


    // DON'T FORGET to stop the server
    @Override
    public void onDestroy()
    {
        super.onDestroy();
        if (server != null)
            server.stop();
    }

    private class WebServer extends NanoHTTPD {

        public WebServer()
        {
            super(8080);
        }

        @Override
        public Response serve(String uri, Method method, 
                              Map<String, String> header,
                              Map<String, String> parameters,
                              Map<String, String> files) {
            String answer = "";
            try {
                // Open file from SD Card
                File root = Environment.getExternalStorageDirectory();
                FileReader index = new FileReader(root.getAbsolutePath() +
                        "/www/index.html");
                BufferedReader reader = new BufferedReader(index);
                String line = "";
                while ((line = reader.readLine()) != null) {
                    answer += line;
                }
                reader.close();

            } catch(IOException ioe) {
                Log.w("Httpd", ioe.toString());
            }


            return new NanoHTTPD.Response(answer);
        }
    }

}

Évidemment, la classe NanoHTTPD doit être dans le même package.

Vous devez accorder une autorisation Internet dans AndroidManifest.xml.

<uses-permission Android:name="Android.permission.INTERNET" />

et lire l'autorisation de stockage externe.

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>

EDIT: Pour accéder au serveur, ouvrez votre navigateur Web avec l'IP de votre appareil, par ex. 192.168.1.20:8080.

REMARQUES:

39
rendon

Un assez bon code source peut être trouvé ici: https://github.com/Teaonly/Android-eye

Dossier d'actifs Chceck où les fichiers html et JavaScript sont stockés https://github.com/Teaonly/Android-eye/tree/master/assets

TeaServer - implémentation du serveur https://github.com/Teaonly/Android-eye/blob/master/src/teaonly/droideye/TeaServer.Java

MainActivity - initialisation du serveur https://github.com/Teaonly/Android-eye/blob/master/src/teaonly/droideye/MainActivity.Java

9
MP23

Classe WebServer mise à jour (voir la réponse de rendon) qui fonctionne avec la version actuelle de NanoHTTPD:

private class WebServer extends NanoHTTPD {

    public WebServer() {
        super(8080);
    }

    @Override
    public Response serve(IHTTPSession session) {
        String answer = "";
        try {
            // Open file from SD Card
            File root = Environment.getExternalStorageDirectory();
            FileReader index = new FileReader(root.getAbsolutePath() +
                    "/www/index.html");
            BufferedReader reader = new BufferedReader(index);
            String line = "";
            while ((line = reader.readLine()) != null) {
                answer += line;
            }
            reader.close();

        } catch(IOException ioe) {
            Log.w("Httpd", ioe.toString());
        }

        return newFixedLengthResponse(answer);
    }

}
7
Anton Tananaev

Jetez un œil à la façon dont je sers les fichiers HTML et les autres types de fichiers. J'ai une classe AndroidWebServer qui étend la classe Nanohttpd. Ceci est ma méthode de réponse ->

    public Response serve(IHTTPSession session) {
    String uri=session.getUri();
    String msg = "<html><body><h1>Hello server</h1>\n";

    File [] arrayfile;

    int i=0;

    try{
        session.parseBody(new HashMap<String, String>());
    }catch (ResponseException | IOException r){
        r.printStackTrace();
    }


    Map<String, String> parms = session.getParms();
    if (parms.get("username") == null) {
        msg += "<form action='?' method='get'>\n  <p>Your name: <input type='text' name='username'></p>\n" + "</form>\n";
    } else {
        msg += "<p>Hello, " + parms.get("username") + "!</p>";
    }
    msg += "<br><br><a href='/Open_rap'>Open Image of Lionel Messi</a><br><br>";
    msg += "<br><br><a href='/files'>Browse Files</a><br><br>";
    msg += "<br><br><a href='/getmethod'>GET METHOD OPERATION</a><br><br>";
    msg += "<br><br><a href='/postmethod'>POST METHOD OPERATION</a><br><br>";
    msg += "<br><br><a href='/jquery'>JQUERY OPERATION</a><br><br>";
    if(uri.equals("/hello")){
            String response="Hello World";
            return  newFixedLengthResponse(response);
    }
    else if(uri.equals("/getmethod")){
        String html="<html><head><h1>Welcome to the Form</h1><head/><body>";

        if(parms.get("name")==null){
            html +="<form action='' method='get'> \n " +
                    "<p>Enter Your Name:</p> <input type='text' name='name'>" +
                    "</form>" +
                    "</body>";
        }
        else{
            html +="<p>Hello Mr. "+ parms.get("name") +"</p>"+
                    "</body> ";
        }

        html +="</html>";
        return newFixedLengthResponse(html);

    }
    else if(uri.equals("/postmethod")){
        String html="<html><head><h1>Welcome to the Form</h1><head/><body>";
        Map<String, String> files = new HashMap<String, String>();
        Method method = session.getMethod();
        String postParameter="";


        html +="<form action='' method='post'> \n " +
                "<p>Enter Your Name:</p> <input type='text' name='name'>" +
                "</form>";

        if (Method.POST.equals(method) || Method.PUT.equals(method)) {
            try {
                session.parseBody(files);
            } catch (IOException ioe) {
                try {
                   // return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("Exception", e.getMessage());
                }
            } catch (ResponseException re) {
                try {
                   // return newFixedLengthResponse(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("Exception", re.getMessage());
                }
            }
        }
        html +="</body></html>";
        String postBody = session.getQueryParameterString();
        postParameter = session.getParms().get("name");
        Log.d("Postbody",postBody+"\n"+postParameter);
        if(postParameter!=null){
            String html1="<html><head><h1>"+ postParameter +"</h1><head></html>";
            return newFixedLengthResponse(html1);
        }
        return newFixedLengthResponse(Response.Status.OK,"text/html",html);
    }

    else if(uri.equals("/Open_rap")){

        File root= Environment.getExternalStorageDirectory();
        FileInputStream fis = null;
        File file = new File(root.getAbsolutePath() + "/www/messi.jpg");
        Log.d("Path",root.getAbsolutePath());
        try{
            if(file.exists())
            {
                fis = new FileInputStream(file);

            }
            else
                Log.d("FOF :", "File Not exists:");
        }catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }


        return newFixedLengthResponse(Response.Status.OK,"image/jpeg",fis, file.length() );
    }
  else {
        return newFixedLengthResponse(msg + "</body></html>\n");
    }

}

Comme vous pouvez le voir, j'ai implémenté GET et POST. Vous pouvez les trouver dans cette partie du code uri.equals("/getmethod") et uri.equals("/getmethod").
De plus, vous pouvez voir la partie -> uri.equals("/openrap"), ici je sers un fichier JPG au navigateur du client et l'image est présente dans le répertoire interne à /www/ dossier.
Envoyez-moi un ping si vous avez des doutes.

3
Shan Singh

Essayez ceci ... Créez 2 packages (activité, util), uniquement pour l'organisation En activité, créez la classe MainActivity.Java dans util créez la classe AndroidWebServer.Java

package awserverfatepi.com.activity;
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.DialogInterface;
import Android.content.Intent;
import Android.content.IntentFilter;
import Android.net.ConnectivityManager;
import Android.net.NetworkInfo;
import Android.net.wifi.WifiManager;
import Android.support.design.widget.CoordinatorLayout;
import Android.support.design.widget.FloatingActionButton;
import Android.support.design.widget.Snackbar;
import Android.support.v4.content.ContextCompat;
import Android.support.v7.app.AlertDialog;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.view.KeyEvent;
import Android.view.View;
import Android.widget.EditText;
import Android.widget.TextView;

import awserverfatepi.com.R;
import awserverfatepi.com.util.AndroidWebServer;

public class MainActivity extends AppCompatActivity {

    private static final int DEFAULT_PORT = 8080;

    private AndroidWebServer androidWebServer;
    private BroadcastReceiver broadcastReceiverNetworkState;
    private static boolean isStarted = false;

    private CoordinatorLayout coordinatorLayout;
    private EditText editTextPort;
    private FloatingActionButton floatingActionButtonOnOff;
    private View textViewMessage;
    private TextView textViewIpAccess;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initGui();
        setIpAccess();
        floatingActionButtonOnOff = (FloatingActionButton) findViewById(R.id.floatingActionButtonOnOff);
        floatingActionButtonOnOff.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isConnectedInWifi()) {
                    if (!isStarted && startAndroidWebServer()) {
                        isStarted = true;
                        textViewMessage.setVisibility(View.VISIBLE);
                        floatingActionButtonOnOff.setBackgroundTintList(ContextCompat.getColorStateList(MainActivity.this,
                                R.color.colorGreen));
                        editTextPort.setEnabled(false);
                    } else if (stopAndroidWebServer()) {
                        isStarted = false;
                        textViewMessage.setVisibility(View.INVISIBLE);
                        floatingActionButtonOnOff.setBackgroundTintList(ContextCompat.getColorStateList(MainActivity.this,
                                R.color.colorRed));
                        editTextPort.setEnabled(true);
                    }
                } else {
                    Snackbar.make(coordinatorLayout, getString(R.string.wifi_message), Snackbar.LENGTH_LONG).show();
                }
            }
        });

        initBroadcastReceiverNetworkStateChanged();
    }

    private void initGui() {
        coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
        editTextPort = (EditText) findViewById(R.id.editTextPort);
        textViewMessage = findViewById(R.id.textViewMessage);
        textViewIpAccess = (TextView) findViewById(R.id.textViewIpAccess);
    }

    private boolean startAndroidWebServer() {
        if (!isStarted) {
            int port = getPortFromEditText();
            try {
                if (port == 0) {
                    throw new Exception();
                }
                androidWebServer = new AndroidWebServer(port);
                androidWebServer.start();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                Snackbar.make(coordinatorLayout, "A porta " + port + " não está funcionando, por favor altere para outra no intervalo" +
                        " entre 1000 e 9999.", Snackbar.LENGTH_LONG).show();
            }
        }
        return false;
    }

    private boolean stopAndroidWebServer() {
        if (isStarted && androidWebServer != null) {
            androidWebServer.stop();
            return true;
        }
        return false;
    }

    private void setIpAccess() {
        textViewIpAccess.setText(getIpAccess());
    }

    private void initBroadcastReceiverNetworkStateChanged() {
        final IntentFilter filters = new IntentFilter();
        filters.addAction("Android.net.wifi.WIFI_STATE_CHANGED");
        filters.addAction("Android.net.wifi.STATE_CHANGE");
        broadcastReceiverNetworkState = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                setIpAccess();
            }
        };
        super.registerReceiver(broadcastReceiverNetworkState, filters);
    }

    private String getIpAccess() {
        WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
        int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
        final String formatedIpAddress = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
                (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));
        return "http://" + formatedIpAddress + ":";
    }

    private int getPortFromEditText() {
        String valueEditText = editTextPort.getText().toString();
        return (valueEditText.length() > 0) ? Integer.parseInt(valueEditText) : DEFAULT_PORT;
    }

    public boolean isConnectedInWifi() {
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        NetworkInfo networkInfo = ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()
                && wifiManager.isWifiEnabled() && networkInfo.getTypeName().equals("WIFI")) {
            return true;
        }
        return false;
    }

    public boolean onKeyDown(int keyCode, KeyEvent evt) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (isStarted) {
                new AlertDialog.Builder(this)
                        .setTitle(R.string.warning)
                        .setMessage(R.string.dialog_exit_message)
                        .setPositiveButton(getResources().getString(Android.R.string.ok), new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                finish();
                            }
                        })
                        .setNegativeButton(getResources().getString(Android.R.string.cancel), null)
                        .show();
            } else {
                finish();
            }
            return true;
        }
        return false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopAndroidWebServer();
        isStarted = false;
        if (broadcastReceiverNetworkState != null) {
            unregisterReceiver(broadcastReceiverNetworkState);
        }
    }

}

Dans AndroidWebserver.Java

package awserverfatepi.com.util;
import Java.util.Map;
import fi.iki.elonen.NanoHTTPD;

public class AndroidWebServer extends NanoHTTPD {

    public AndroidWebServer(int port) {
        super(port);
    }

    public AndroidWebServer(String hostname, int port) {
        super(hostname, port);
    }

    @Override
    public Response serve(IHTTPSession session) {
        String msg = "<html><body><h1>Hello World</h1>\n";
        Map<String, String> parms = session.getParms();
        if (parms.get("username") == null) {
            msg += "<form action='?' method='get'>\n  <p>Seu nome: <input type='text' name='username'></p>\n" + "</form>\n";
        } else {
            msg += "<p>Hello, " + parms.get("username") + "!</p>";
        }
        return newFixedLengthResponse( msg + "</body></html>\n" );
    }
}

N'oubliez pas Manifest.xml

<uses-permission Android:name="Android.permission.INTERNET" />
<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE" />
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE" />
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />

Enfin

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/coordinatorLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <ImageView
            Android:layout_width="match_parent"
            Android:layout_height="150dp"
            Android:scaleType="centerCrop"
            Android:src="@drawable/header" />

        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="0dp"
            Android:layout_weight="1"
            Android:background="@color/colorPrimaryLight"
            Android:gravity="center"
            Android:orientation="vertical">

            <LinearLayout
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:orientation="horizontal">

                <TextView
                    Android:id="@+id/textViewIpAccess"
                    Android:layout_width="wrap_content"
                    Android:layout_height="wrap_content"
                    Android:text="http://000.000.000.000:"
                    Android:textColor="@Android:color/white"
                    Android:textSize="20sp"
                    Android:textStyle="bold" />

                <EditText
                    Android:id="@+id/editTextPort"
                    Android:layout_width="60dp"
                    Android:layout_height="wrap_content"
                    Android:gravity="center"
                    Android:hint="8080"
                    Android:inputType="numberDecimal"
                    Android:maxLength="4"
                    Android:text="8080"
                    Android:textColor="@Android:color/white"
                    Android:textSize="20sp"
                    Android:textStyle="bold" />

            </LinearLayout>

            <TextView
                Android:id="@+id/textViewMessage"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_marginLeft="50dp"
                Android:layout_marginRight="50dp"
                Android:layout_marginTop="50dp"
                Android:gravity="center"
                Android:text="@string/message"
                Android:textColor="@Android:color/white"
                Android:textSize="18sp"
                Android:visibility="invisible" />

        </LinearLayout>

    </LinearLayout>

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/floatingActionButtonOnOff"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="end|bottom"
        Android:layout_margin="16dp"
        Android:elevation="4dp"
        Android:src="@drawable/on_btn"
        app:backgroundTint="@color/colorRed" />

</Android.support.design.widget.CoordinatorLayout>
3
Ênio Rodrigues