I have a custom class in Android, very simple which I call to download and start the share intent on files in my app which come from a specific URL
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Environment;
import java.io.File;
public class DownloadAndShare
{
Activity activity;
Context context;
ProgressDialog dialog;
String URL;
public DownloadAndShare(Activity activity, Context context, String URL) {
this.activity = activity;
this.context = context;
this.URL = URL;
}
public void startSharing()
{
//Start shareIntent for this file
File fileWithinMyDir = Environment.getExternalStorageDirectory();
String[] fn = URL.split("/");
String fileName = fn[fn.length-1];
File storageFolder = new File(fileWithinMyDir.toString() + "/myappname");
//If storage folder does not yet exists, create it
if(!storageFolder.exists()){
storageFolder.mkdirs();
}
final String PATH = fileWithinMyDir.toString() + "/myappname/" + fileName;
//Check if file exists in internal storage
File file = new File(PATH.replace(" ", ""));
if (!file.exists()){
//file does not exists, download to internal storage for use
new executeDownloadAndShare().execute(PATH.replace(" ", ""), URL);
} else {
Intent shareIntent = Globals.getShareIntent(PATH.replace(" ", ""), false);
activity.startActivity(Intent.createChooser(shareIntent, "Share using..."));
}
}
private class executeDownloadAndShare extends AsyncTask<String, Integer, Integer> {
String filePath;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(context, "", context.getResources().getString(R.string.general_msg_please_wait));
}
#Override
protected Integer doInBackground(String... params) {
filePath = params[0];
try {
Globals.DownloadFromUrl(params[0], params[1]);
} catch (Exception e) {
return AppConstants.STATUS_FAIL;
}
return AppConstants.STATUS_SUCCESS;
}
#Override
protected void onPostExecute(Integer result) {
dialog.dismiss();
Intent shareIntent = Globals.getShareIntent(filePath, false);
activity.startActivity(Intent.createChooser(shareIntent, "Share using..."));
}
}
}
For some reason, when I try to create an instance of it inside one of my files, it needs to have the full com.myappname.android.MyCustomClass myCustomClass = new com.myappname.android.MyCustomClass(); In order files I have it as just MyCustomClass myCustomClass = new MyCustomClass() and it works fine, however in a few files it wants the entire path.
Does anyone have any insight as to why this occurs? Both files where I call this are both extending Fragment, and one works while the other needs the full path. I thought maybe it was something with a private method where it should be public etc, but I can't find anything wrong.
Clean you project and uninstall app from device/emulator before starting it again. If that not help, restart Android Studio.
Related
i want to get the contents of a file in dropbox. in the internet i found only the options to download the file. but it gives me the file not found exception.
java.io.FileNotFoundException: /storage/emulated/0/Download/Temp/test.txt (No such file or directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
at com.codeyard.teleprompter.DownloadFileTask.doInBackground(DownloadFileTask.java:72)
at com.codeyard.teleprompter.DownloadFileTask.doInBackground(DownloadFileTask.java:23)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:762)
2019-11-26 13:25:59.512 15240-15240/com.codeyard.teleprompter E/ViewRootImpl: sendUserActionEvent() returned.
how can i get ONLY THE CONTENTS and not DOWNLOAD the file completely
package com.codeyard.teleprompter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import com.dropbox.core.DbxException;
import com.dropbox.core.v2.DbxClientV2;
import com.dropbox.core.v2.files.FileMetadata;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Task to download a file from Dropbox and put it in the Downloads folder
*/
class DownloadFileTask extends AsyncTask<String, Void, File> {
private static final String TAG = "TELEPROMPTER";
#SuppressLint("StaticFieldLeak")
private final Context mContext;
private final DbxClientV2 mDbxClient;
private final Callback mCallback;
private Exception mException;
public interface Callback {
void onDownloadComplete(File result);
void onError(Exception e);
}
DownloadFileTask(Context context, DbxClientV2 dbxClient, Callback callback) {
mContext = context;
mDbxClient = dbxClient;
mCallback = callback;
}
#Override
protected void onPostExecute(File result) {
super.onPostExecute(result);
if (mException != null) {
mCallback.onError(mException);
} else {
mCallback.onDownloadComplete(result);
}
}
#Override
protected File doInBackground(String... params) {
String metadata = params[0];
try {
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS);
File file = new File(path, metadata);
// Make sure the Downloads directory exists.
if (!path.exists()) {
if (!path.mkdirs()) {
mException = new RuntimeException("Unable to create directory: " + path);
}
} else if (!path.isDirectory()) {
mException = new IllegalStateException("Download path is not a directory: " + path);
return null;
}
//Download the file.
try (OutputStream outputStream = new FileOutputStream(file)) {
mDbxClient.files().download(metadata.toLowerCase())
.download(outputStream);
}
// Tell android about the file
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
mContext.sendBroadcast(intent);
return file;
} catch (DbxException | IOException e) {
mException = e;
}
return null;
}
}
maybe there is any method to call from the dropbox api v2???
what i want is that only the text contetn into like a string or something. the code is from the official github repo
Your problem has nothing to do with downloading but all wit statement
(OutputStream outputStream = new FileOutputStream(file))
But instead of a FIleOutputStream you could open a ByteArrayOutputStream.
In that way you keep alll bytes in memory and dont have to save.
I am trying to get a simple Android app working with the Pd library I have integrated within my eclipse environment.
I have successfully build and compiled an example project called "CircleOfFifths" which proves that the library has been integrated fine in eclipse.
I am using cordova/phonegap and trying to create a plugin for libpd. All the plugin communication with the javascript file on the front-end is working fine.
The code seems to initialise and load the patch fine. It also goes into the play() method but I don't get any output. I am expecting to hear the sine wave.
I followed this tutorial on YouTube.
My code can be viewed here, and the patch is here.
Can anyone help me figure out where I can be going wrong?
My ultimate objective is to use a live audio from microphone and process that audio and return immediately with applied Pd patch (patch is ready and created for this) but before I go to that stage I want to make sure that I get some sort of output from the existing patch. Same patch as the one above in the YouTube tutorial.
package com.test.libpd;
import java.io.File;
import java.io.IOException;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.puredata.android.io.AudioParameters;
import org.puredata.android.io.PdAudio;
import org.puredata.android.utils.PdUiDispatcher;
import org.puredata.core.PdBase;
import org.puredata.core.utils.IoUtils;
import android.content.Context;
import android.util.Log;
import com.sgil.libpddemo.R;
public class Libpd extends CordovaPlugin {
private static final String TAG = "libpd_plugin";
private Exception exception;
private Context AppContext;
private PdUiDispatcher dispatcher;
private static final int MIN_SAMPLE_RATE = 44100;
public Libpd() { // constructor
}
private Context getApplicationContext() {
return this.cordova.getActivity().getApplicationContext();
}
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
Log.v(TAG, "Init LIBPD PLUGIN");
}
public boolean execute(final String action, final JSONArray args,
final CallbackContext callbackContext) throws JSONException {
cordova.getActivity().runOnUiThread(new Runnable() {
// #SuppressLint("NewApi")
public void run() {
Log.v(TAG, "Plugin received:" + action);
Libpd libpd = new Libpd();
libpd.AppContext = getApplicationContext();
try {
libpd.initPd(libpd.AppContext);
libpd.loadPatch(libpd.AppContext);
} catch (IOException e) {
Log.e(TAG, e.toString());
// libpd.finish();
}
if (action.equals("playRec")) {
// MediaRecordMethod mediaRecordMethod = new
// MediaRecordMethod(action);
// mediaRecordMethod.init();
libpd.play();
}
if (action.equals("stopRec")) {
libpd.onPause();
}
if (action.equals("startRec")) {
libpd.record("start");
libpd.play();
}
}
});
return true;
}
private void initPd(Context ctx) throws IOException {
AudioParameters.init(ctx);
// Configure the audio glue
int sampleRate = AudioParameters.suggestSampleRate();
int srate = Math.max(MIN_SAMPLE_RATE, AudioParameters.suggestSampleRate());
// int sampleRate = 64;
int inpch = AudioParameters.suggestInputChannels();
int outpch = AudioParameters.suggestOutputChannels();
PdAudio.initAudio(srate, 0, outpch, 8, true);
// Create and install the dispatcher
dispatcher = new PdUiDispatcher();
PdBase.setReceiver(dispatcher);
}
private void loadPatch(Context ctx) throws IOException {
File dir = ctx.getFilesDir();
Log.v(TAG, "path:" + dir.getAbsolutePath().toString());
//File dir = new File("/sdcard/mypatches");
IoUtils.extractZipResource(
ctx.getResources().openRawResource(R.raw.simplepatch), dir, true);
File patchFile = new File(dir, "simplepatch.pd");
PdBase.openPatch(patchFile.getAbsolutePath());
//PdAudio.startAudio(ctx);
//this.record("start");
}
private void record(String startorStop) {
if (startorStop.equals("start")) {
PdBase.sendSymbol("recordfilename", "x.aiff");
PdBase.sendBang("openfile");
PdBase.sendBang("record");
} else {
PdBase.sendBang("stoprecording");
}
}
// play back the last recording from the file called 'recorded'
public void play() {
//PdBase.sendSymbol("playfilename", "x.aiff");
//PdBase.sendBang("readfile");
//PdBase.sendBang("play");
Float val = 1.0f;
PdBase.sendFloat("onOff", val);
}
protected void onPause() {
PdAudio.stopAudio();
PdAudio.release();
PdBase.release();
}
}
your code never starts the audio-processing.
For whatever reasons youhave uncommented the line
PdAudio.startAudio(ctx)
So I've got a simple Android App that can upload a file to an AWS S3 bucket, I'm looking to see how I can go about storing the filename in the object URL using metadata support from AWS.
How would I got about doing so?
Below is my MainActivity.java file:
package com.example.s3imagetest;
import java.net.URL;
import java.util.Date;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.ResponseHeaderOverrides;
public class MainActivity extends Activity {
private AmazonS3Client s3Client = new AmazonS3Client(
new BasicAWSCredentials(Constants.ACCESS_KEY_ID,
Constants.SECRET_KEY));
private Button selectPhoto = null;
private Button showInBrowser = null;
private static final int PHOTO_SELECTED = 1;
/** Called when the activity is first created. */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("OnCreate", "OnCreate Was Called");
s3Client.setRegion(Region.getRegion(Regions.EU_WEST_1));
setContentView(R.layout.activity_main);
selectPhoto = (Button) findViewById(R.id.button1);
selectPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the image picker.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, PHOTO_SELECTED);
}
});
showInBrowser = (Button) findViewById(R.id.button2);
showInBrowser.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new S3GeneratePresignedUrlTask().execute();
}
});
}
// This method is automatically called by the image picker when an image is
// selected.
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case PHOTO_SELECTED:
if(resultCode == RESULT_OK) {
Uri selectedImage = imageReturnedIntent.getData();
new S3PutObjectTask().execute(selectedImage);
}
}
}
// Display an Alert message for error or failure
protected void displayAlert(String title, String message) {
AlertDialog.Builder confirm = new AlertDialog.Builder(this);
confirm.setTitle(title);
confirm.setMessage(message);
confirm.setNegativeButton(MainActivity.this.getString(R.string.ok),
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
confirm.show().show();
}
protected void displayErrorAlert(String title, String message) {
AlertDialog.Builder confirm = new AlertDialog.Builder(this);
confirm.setTitle(title);
confirm.setMessage(message);
confirm.setNegativeButton(MainActivity.this.getString(R.string.ok),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();
}
});
confirm.show().show();
}
private class S3PutObjectTask extends AsyncTask<Uri, Void, S3TaskResult> {
ProgressDialog dialog;
protected void onPreExecute() {
Log.v("S3PutObjectTask", "Its Beginning ");
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage(MainActivity.this.getString(R.string.uploading));
dialog.setCancelable(false);
dialog.show();
Log.v("S3PutObjectTask", "onPreExecute Done");
}
protected S3TaskResult doInBackground(Uri... uris) {
Log.v("S3TaskResult", "Uri" + uris);
if (uris == null || uris.length != 1) {
return null;
}
// The file location of the image selected.
Uri selectedImage = uris[0];
ContentResolver resolver = getContentResolver();
String fileSizeColumn[] = { OpenableColumns.SIZE };
Cursor cursor = resolver.query(selectedImage, fileSizeColumn, null,
null, null);
cursor.moveToFirst();
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
String size = null;
if (!cursor.isNull(sizeIndex)) {
size = cursor.getString(sizeIndex);
}
cursor.close();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(resolver.getType(selectedImage));
if (size != null) {
metadata.setContentLength(Long.parseLong(size));
}
S3TaskResult result = new S3TaskResult();
// Put the image data into S3.
try {
Log.v("PutData into S3", "Data has bee sent");
//s3Client.createBucket(Constants.getPictureBucket());
PutObjectRequest por = new PutObjectRequest(
Constants.PICTURE_BUCKET, Constants.PICTURE_NAME,
resolver.openInputStream(selectedImage), metadata);
Log.v("PubtObjectRequest", "Selected Image");
s3Client.putObject(por);
Log.v("S3Client.putOb", "por");
Toast.makeText(getApplicationContext(), "Photo Upload Success", Toast.LENGTH_LONG).show();
} catch (Exception exception) {
result.setErrorMessage(exception.getMessage());
}
return result;
}
protected void onPostExecute(S3TaskResult result) {
dialog.dismiss();
if (result.getErrorMessage() != null) {
displayErrorAlert(
MainActivity.this
.getString(R.string.upload_failure_title),
result.getErrorMessage());
}
}
}
private class S3GeneratePresignedUrlTask extends
AsyncTask<Void, Void, S3TaskResult> {
protected S3TaskResult doInBackground(Void... voids) {
S3TaskResult result = new S3TaskResult();
try {
// Ensure that the image will be treated as such.
Log.v("S3GeneratePresignedUrlTask", "S3TaskResult");
ResponseHeaderOverrides override = new ResponseHeaderOverrides();
override.setContentType("image/jpeg");
// Generate the pre-signed URL.
// Added an hour's worth of milliseconds to the current time.
Date expirationDate = new Date(
System.currentTimeMillis() + 3600000);
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(
Constants.PICTURE_BUCKET, Constants.PICTURE_NAME);
urlRequest.setExpiration(expirationDate);
urlRequest.setResponseHeaders(override);
URL url = s3Client.generatePresignedUrl(urlRequest);
result.setUri(Uri.parse(url.toURI().toString()));
} catch (Exception exception) {
result.setErrorMessage(exception.getMessage());
}
return result;
}
protected void onPostExecute(S3TaskResult result) {
if (result.getErrorMessage() != null) {
displayErrorAlert(
MainActivity.this
.getString(R.string.browser_failure_title),
result.getErrorMessage());
} else if (result.getUri() != null) {
// Display in Browser.
startActivity(new Intent(Intent.ACTION_VIEW, result.getUri()));
}
}
}
private class S3TaskResult {
String errorMessage = null;
Uri uri = null;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public Uri getUri() {
return uri;
}
public void setUri(Uri uri) {
this.uri = uri;
}
}
}
From
http://docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/
setUserMetadata(Map) seems like it might be what you are looking for, although I don't think this is the best way to approach this problem.
Sets the
custom user-metadata for the associated object.
Amazon S3 can store additional metadata on objects by internally
representing it as HTTP headers prefixed with "x-amz-meta-". Use
user-metadata to store arbitrary metadata alongside their data in
Amazon S3. When setting user metadata, callers should not include the
internal "x-amz-meta-" prefix; this library will handle that for them.
Likewise, when callers retrieve custom user-metadata, they will not
see the "x-amz-meta-" header prefix.
User-metadata keys are case insensitive and will be returned as
lowercase strings, even if they were originally specified with
uppercase strings.
Note that user-metadata for an object is limited by the HTTP request
header limit. All HTTP headers included in a request (including user
metadata headers and other standard HTTP headers) must be less than
8KB.
From your description, it sounds like this is an app where users can upload photos and view them from a browser as well as the phone. However, you want it so that when the user deletes a photo from the browser, the corresponding local copy will also be deleted on the phone.
I think you could probably accomplish this with the setUserMetadata method, by passing up metadata that describes the path. However, this would be very cumbersome because the metadata is only lower case, and unfortunately the path and file names are not guaranteed to be(I think?). So, you'd need your own way of mapping lower case strings to upper and lower case strings, which adds a lot of unnecessary complexity.
I feel like it would be better if you set up a database to hold the mappings from S3 file names to their respective local paths. You could do this either on the Android device, which would be much easier but could exhibit weird behavior if the user tries the data. You could also do this on your own back end, which probably makes more sense if you are going to be sending out push notifications to your users to handle deletion anyway, since you could just push the path to them.
An even bigger potential issue is that you have to differentiate between devices, although you could solve that by just keeping a unique id associated with each device in your table. There's also the problem of what to do when the user decides to move the picture.
In any case, those things aren't really relevant to the question at hand. To answer your question, you COULD do this with the metadata but it would be ill advised since it adds a lot of complexity with seeming little upside. If you are looking for the simplest approach(handling all this client side) then I would probably suggest you try to use Cognito and DynamoDB to directly add a row to some DynamoDB table from your app. Make sure you specify the correct permissions to both allow you to do this and also to not allow any extra power to the user if you do take this approach.
Hope some of that helped!
I am trying to use NanoHTTP to serve up an HTML file with help of Android.
Currently i'm able to do display the page. I'm also new to andriod. The issue is not having a clear picture how to refer the images and css for that html file even after i have taken the files with help of AssetManager. Below i provided the entire code. Could somebody help me on this.
Note: Other permission settings are fine like InternetPermission. Only not having an idea how refer the other supported files (css, images, javascript files) for the html.
package com.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 MainActivity extends Activity
{
private WebServer server;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AssetManager assetManager = getAssets();
String imagePath = "fileapp/image";
String cssPath = "fileapp/css";
String files[] = null;
try {
files = assetManager.list(imagePath);
Log.i("Image", files[0]);
Log.w("Image", files[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("Image ",e.getMessage());
}
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) {
StringBuilder msg = new StringBuilder("<html><head><title>" + heading + "</title>" +
**"<link href=\"../../../fileapp/css/style.css\" rel=\"stylesheet\">" +**
"</head>"
+ "<body>");
msg.append("**<div class=\"jumbotron-sm\"> <img src=\"../../../fileapp/image/logo.png\">**</div>");
msg.append("<div>My Body Content go here......</div>");
msg.append("</body>"
+ "</html>");
return msg.toString();
}
}
}
Kindly let me know in case of any further details.
Thanks advance for your answers.
I would like to add a webserver to my android application for uploading small files to the phone.
The user would start the webserver from the phone by hitting a button. He would then see an ip address that can be accessed by any browser from a pc. The website behind this ip address should show a file upload opportunity.
My question is: Is there an open source project similar to my needs? Or how would you recommend doing this?
you can use NanoHttpd link it's very weight android web server that is nicely embbedible..
package .....;
import java.io.IOException;
import java.util.Map.Entry;
import java.util.Properties;
import android.app.Activity;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
public class AndroidWebServerActivity extends Activity {
private static final int PORT = 8765;
private TextView hello;
private MyHTTPD server;
private Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onResume() {
super.onResume();
try {
server = new MyHTTPD();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
if (server != null)
server.stop();
}
private class MyHTTPD extends NanoHTTPD {
public MyHTTPD() throws IOException {
super(PORT, null);
}
#Override
public Response serve(String uri, String method, Properties header, Properties parms, Properties files) {
final StringBuilder buf = new StringBuilder();
for (Entry<Object, Object> kv : header.entrySet())
buf.append(kv.getKey() + " : " + kv.getValue() + "\n");
handler.post(new Runnable() {
#Override
public void run() {
}
});
final String html = "<html><head><head><body><h1>Hello, World</h1></body></html>";
return new NanoHTTPD.Response(HTTP_OK, MIME_HTML, html);
}
}
}