It has been days I am struggling with this problem. I want to create a local android server to let other devices download a file in LAN. So far i have created a socket server that writes a pdf file along with header on output stream, but it is not working. When url is hit on web browser almost 95% of the data is downloaded without any problem after that download fails, it shows network problem(In Google chrome).
Following is the code to create server:
class VideoStreamServer {
public void startServer() {
outFilePath = getActivity().getExternalFilesDir("/") + "/pdf.pdf";
outFile = new File(outFilePath);
Runnable videoStreamTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket socket = new ServerSocket(port);
System.out.println("Waiting for client to connect.");
while (true) {
Socket client = socket.accept();
BufferedOutputStream os = new BufferedOutputStream(client.getOutputStream());
FileInputStream in = new FileInputStream(outFile);
BufferedInputStream inFromClient = new BufferedInputStream(client.getInputStream());
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\r\n");
sb.append("Accept-Ranges: bytes\r\n");
sb.append("Connection: close\r\n");
sb.append("Content-Length: " + in.available() + "\r\n");
sb.append("Content-Disposition: attachment; filename=file.pdf\r\n");
sb.append("Content-Type: application/pdf \r\n");
sb.append("\r\n");
byte[] data = new byte[1024];
int length;
//inFromClient.read(data);
//System.out.println("request from client"+getStreamData(inFromClient));
System.out.println("Thread Started");
//System.setProperty("http.keepAlive", "false");
os.write(sb.toString().getBytes());
while ((length = in.read(data)) != -1) {
os.write(data, 0, length);
}
os.close();
client.close();
socket.close();
in.close();
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread streamServer = new Thread(videoStreamTask);
streamServer.start();
}
}
Any help would be appreciated.
EDIT1
public String getStreamData(InputStream in) {
StringBuffer buffer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
try {
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return buffer.toString();
}
Related
I tried using many codes I've found for downloading files with an AsyncTask with no success yet.
I get an error on the logcat: E/Error:: No such file or directory.
Despite looking for solutions for this error, couldn't find What's missing or wrong.
This is the doInBackground method in which I assume something is missing/wrong:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new DownloadJSON().execute("http://api.androidhive.info/json/movies.json");
}
protected String doInBackground(String...fileUrl) {
int count;
try {
String root = "data/data/com.example.jsonapp2";
URL url = new URL(fileUrl[0]);
URLConnection connection = url.openConnection();
connection.connect();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
File fileName = new File(root+"/movies.json");
boolean existsOrNot = fileName.createNewFile(); // if file already exists will do nothing
// Output stream to write file
OutputStream output = new FileOutputStream(fileName,false);
byte data[] = new byte[1024];
System.out.println("Downloading");
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
Thanks.
Didn't want to bombard with redundant code. If some other code is needed, I'd love to provide it.
UPDATED ANSWER
this is working for me, write file in local storage and read it again on method PostExecute
class DownloadJSON extends AsyncTask<String, Void, Void>{
String fileName;
String responseTxt;
String inputLine;
String folder;
#Override
protected Void doInBackground(String... strings) {
try {
String root = "data/data/com.example.jsonapp2";
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
//Set methods and timeouts
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(15000);
urlConnection.setConnectTimeout(15000);
urlConnection.connect();
//Create a new InputStreamReader
InputStreamReader streamReader = new
InputStreamReader(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
StringBuilder response = new StringBuilder();
//Check if the line we are reading is not null
while((inputLine = reader.readLine()) != null){
response.append(inputLine);
}
//Close our InputStream and Buffered reader
reader.close();
streamReader.close();
responseTxt = response.toString();
Log.d(TAG, "doInBackground: responseText " + responseTxt);
// PREPARE FOR WRITE FILE TO DEVICE DIRECTORY
FileOutputStream fos = null;
fileName = "fileName.json";
folder = fileFolderDirectory();
try {
fos = new FileOutputStream(new File(folder + fileName));
//fos = openFileOutput(folder + fileName, MODE_PRIVATE);
fos.write(responseTxt.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null){
fos.close();
}
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// -- THIS METHOD IS USED TO ENSURE YOUR FILE AVAILABLE INSIDE LOCAL DIRECTORY -- //
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(folder +fileName));
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String text;
while ((text = br.readLine()) != null) {
sb.append(text).append("\n");
}
Toast.makeText(TestActivity.this, "result " + sb.toString(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ops, almost forget this method
public static String fileFolderDirectory() {
String folder = Environment.getExternalStorageDirectory() + File.separator + "write_your_app_name" + File.separator;
File directory = new File(folder);
if(!directory.exists()){
directory.mkdirs();
}
return folder;
}
Your root is wrong
String root = "data/data/package.appname";
make sure your root contains right package name or file path.
package name which should be your application id
in my application i am using below code that returns input stream
QBContent.downloadFileById(fileId, new QBEntityCallback<InputStream>() {
#Override
public void onSuccess(final InputStream inputStream, Bundle params) {
long length = params.getLong(Consts.CONTENT_LENGTH_TAG);
Log.i(TAG, "content.length: " + length);
// use inputStream to download a file
}
#Override
public void onError(QBResponseException errors) {
}
}, new QBProgressCallback() {
#Override
public void onProgressUpdate(int progress) {
}
});
now i want to covert input steam into file then want to do two things with that file
1. how can i save it to user's phone storage
2. save it temporarily and display's it in pdf viewer using intent
note: returned file will be in pdf formal
You did not mentionned if you wanted to store in external or internal storage, I wrote this example for internal storage
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line).append('\n');
}
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("file.txt", Context.MODE_PRIVATE));
outputStreamWriter.write(total.toString());
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
Don't forget to use try/catch and close what needs to be closed
You can use below code to store InputStream in File.
But you need to pass file path and where you want to store file in storage.
InputStream inputStream = null;
BufferedReader br = null;
try {
// read this file into InputStream
inputStream = new FileInputStream("/Users/mkyong/Downloads/file.js");
br = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
System.out.println(sb.toString());
System.out.println("\nDone!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am learning Android and porting my Windows app to Android platform. I need an advice how to download a small text file and read content of this file.
I have following code in my Windows app, I need to rewrite it for Android app:
string contents = "file.txt";
string neturl = "http://www.example.com/file.txt";
HttpClient client = new HttpClient();
try {
HttpResponseMessage message = await client.GetAsync(neturl);
StorageFolder folderForFile = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile fileWithContent = await folderForFile.CreateFileAsync(channels, CreationCollisionOption.ReplaceExisting);
byte[] bytesToWrite = await message.Content.ReadAsByteArrayAsync();
await FileIO.WriteBytesAsync(fileWithContent, bytesToWrite);
var file = await folderForFile.GetFileAsync(contents);
var text = await FileIO.ReadLinesAsync(file);
foreach (var textItem in text)
{
string[] words = textItem.Split(',');
...
I have found what on Android I need to create following class for async download
public class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// download the file
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream
OutputStream output = new FileOutputStream("file.txt");
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
In the code above I try to download file and name it as "file.txt", but get exception 'FileNotFoundException file.txt open failed: EROFS (Read-only file system)", I need to save it internally (I do not want to let users to see this file in the file explorers) and rewrite file if it exists.
And I try to execute this task and read file
void DownloadAndReadContent() {
new DownloadFileFromURL().execute("http://www.example.com/file.txt");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(openFileInput("file.txt")));
String str = "";
while ((str = br.readLine()) != null) {
Log.d(LOG_TAG, str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
so downloading to SD card is working
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
InputStream input = new BufferedInputStream(url.openStream(), 8192);
File SDCardRoot = Environment.getExternalStorageDirectory();
SDCardRoot = new File(SDCardRoot.getAbsolutePath() + "/plus");
SDCardRoot.mkdir();
File file = new File(SDCardRoot,"settings.dat");
FileOutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
and reading:
new DownloadFileFromURL().execute("http://www.example.com/file.txt");
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Log.d(LOG_TAG, "SD n\a " + Environment.getExternalStorageState());
return;
}
File sdPath = Environment.getExternalStorageDirectory();
sdPath = new File(sdPath.getAbsolutePath() + "/plus");
File sdFile = new File(sdPath, "settings.dat");
try {
BufferedReader br = new BufferedReader(new FileReader(sdFile));
String str = "";
while ((str = br.readLine()) != null) {
String[] words = str.split(",");
// do some work
}
}
Log.d(LOG_TAG, str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I am running a server which writes a simple Welcome message to a new Client upon Successful connection!
Now I am sure of it that my android device connects to the server but I am unable to receive the welcome text that the server sends.
I am new to socket programming and I am looking for a unified solution to this.
I will paste my code which has a successful outputStream snippet and gets the android connected to the server. I ll leave the InputStream section black, since I need the solution for that!
private ArrayBlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer>(100);
private AtomicBoolean mStop = new AtomicBoolean(false);
private OutputStream mOutputStream = null;
private InputStream mInputStream = null;
private Socket mSocket = null;
private static Thread sNetworkThread = null;
private final Runnable mNetworkRunnable = new Runnable() {
log("starting network thread");
String encoding = "UTF-8";
String output="";
#Override
public void run() {
log("starting network thread");
try {
mSocket = new Socket(ARDUINO_IP_ADDRESS, PORT);
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
} catch (UnknownHostException e1) {
e1.printStackTrace();
mStop.set(true);
} catch (IOException e1) {
e1.printStackTrace();
mStop.set(true);
}
mQueue.clear(); // we only want new values
//Output Stream
try {
while(!mStop.get()){
int val = mQueue.take();
if(val >= 0){
log("sending value "+val);
mOutputStream.write((val+"\n").getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
try {
mStop.set(true);
if(mOutputStream != null) mOutputStream.close();
if(mSocket != null) mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//InputStream
try
{
//Call method to read inputStream
output = readFully(mInputStream,encoding);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Server Message"+output, Toast.LENGTH_SHORT).show();
log("returning from network thread");
sNetworkThread = null;
}
};
Well I added two methods to achieve the inputStream by calling it from the thread. The methods are as follows.
public String readFully(InputStream inputStream, String encoding)
throws IOException {
return new String(readFully(inputStream), encoding);
}
private byte[] readFully(InputStream inputStream)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toByteArray();
}
** The Server returns a String - "Welcome New User"
Well I hv used putty in RAW mode to coonect to the server and it works fine.
StackTrace Logs:
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/>==< ArduinoYun >==<﹕ starting network thread
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] getaddrinfo hn 9, servname NULL, ai_family 0+
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] ht 0x31302e302e302e
03-02 16:46:22.790 11813-12339/com.example.bonny.myapplication D/libc﹕ [NET] getaddrinfo-exit SUCCESS
I need to integrate the inputStream on this thread.
P.S. OutputStream works smoothly from this code!
You need to read one line. Your present code tries to read everything until end of stream, whuch only happens when the peer closes the connection.
public String convertStreamToString(java.io.InputStream is)
{
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try
{
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return sb.toString();
}
Above code might help you in converting InputStream into String.
I hope this will help you.
I need to use the tcp socket connection to get the data from a bluebox, if I input a comment, such as "getcolor", the bluebox will send me the information like"red, blue".
In this case the bluebox as a server and I do not need to program on it, but I have problem to show the information on the EditText.
public class sender {
public static void main(String[] args)throws IOException{
Socket socket = new Socket("192.168.1.176",14111);
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "";
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
String[] line = buffer.split("\n");
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
System.out.print(buffer);
buffer = "";
}
}
in.close();
out.close();
socket.close();
}
}
this java code works, but it fails in the android code below:
public class BlueBoxApp extends Activity {
/** Called when the activity is first created. */
Context appInstance = this;
private EditText info;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
info = (EditText)findViewById(R.id.EditText01);
try{
InetAddress serverAddr = InetAddress.getByName("192.168.1.176");//TCP服务器IP地址
Log.d("TCP", "server,receiving...");
Socket socket = new Socket(serverAddr,14111);
try {
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "getsensorno";
Log.d("TCP", "sending:'"+ms+"'");
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
info.setText(buffer);
buffer = "";
}
}
} catch (Exception e) {
Log.e("TCP", "error",e);
}finally{
socket.close();
}
}catch(Exception e){
Log.e("TCP", "error",e);
}
}
}
what is the problem and how to set a thread for it? Thanks!
The problem, as you indicated, is that you are doing the networking part on the main thread.
Setting a new thread is easy, consider using AsyncTask. Please read the documentation (which is very good) before jumping to implement it, it will make it much easier IMHO.
Also, make sure you have internet permission in your AndroidManifest.xml