Saving string array list to internal file directory android - java

I'm currently developing an android application with makes some user data while running which is saved in two ArrayList. Once the application closes, I need to save the datas on to the internal memory but in my logcat I'm always getting the error IOException file not found.
I'm confused about why it always happen. The following is my code for my activity. Please help me!
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.text.Html;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.Button;
public class MainActivity extends ActionBarActivity {
public static ArrayList<String> myArrayList=new ArrayList<String>();
public static ArrayList<String> myArrayListwr=new ArrayList<String>();
static int close=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
close=1;
System.out.println("Oncreate called");
try{
final File dir = new File(getApplicationContext().getFilesDir() + "/file");
if(!(dir.exists()))
{
dir.mkdirs(); //create folders where write files
}
final File file = new File(dir+ "/lines.txt");
if(!(file.exists())) {
file.createNewFile();
}
BufferedReader br = new BufferedReader(new FileReader(file));
if (br.readLine() == null) {
close=0;
}
br.close();
}
catch (IOException exc) { exc.printStackTrace(); }
try {
if(myArrayList.size()==0 && close!=0)
{
System.out.println("retriving data from file lines");
FileInputStream input =openFileInput("lines.txt"); // Open input stream
DataInputStream din = new DataInputStream(input);
int sz = din.readInt(); // Read line count
for (int i=0;i<sz;i++) { // Read lines
String line = din.readUTF();
myArrayList.add(line);
}
din.close();
}
}
catch (IOException exc) { exc.printStackTrace(); }
try {
if(myArrayListwr.size()==0 && close!=0)
{
System.out.println("retriving data from file lineswr");
final File dirwr = new File(getApplicationContext().getFilesDir() + "/file");
if(!dirwr.exists())
dirwr.mkdirs(); //create folders where write files
final File filewr = new File(dirwr+ "/lineswr.txt");
if(!filewr.exists()) {
filewr.createNewFile();
}
FileInputStream inputwr = openFileInput("lineswr.txt"); // Open input stream
DataInputStream dinwr = new DataInputStream(inputwr);
int szwr = dinwr.readInt(); // Read line count
for (int iwr=0;iwr<szwr;iwr++) { // Read lines
String linewr = dinwr.readUTF();
myArrayListwr.add(linewr);
}
dinwr.close();
}
}
catch (IOException exc) { exc.printStackTrace(); }
Button phy = (Button) findViewById(R.id.button3);
Button mat = (Button) findViewById(R.id.button1);
Button bio = (Button) findViewById(R.id.button2);
Button chem = (Button) findViewById(R.id.button4);
}
#Override
public void onBackPressed() {
super.onBackPressed();
try {
if(myArrayList.size()!=0)
{
System.out.println("inside on back pressed saving data to lines");
//Modes: MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITABLE
String fileName = getApplicationContext().getFilesDir()+"/file/"+ "lines.txt";
FileOutputStream output = openFileOutput("lines.txt",MODE_PRIVATE);
DataOutputStream dout = new DataOutputStream(output);
dout.writeInt(myArrayList.size()); // Save line count
for(String line : myArrayList) // Save lines
dout.writeUTF(line);
dout.flush(); // Flush stream ...
dout.close(); // ... and close.
}
}
catch (IOException exc) { exc.printStackTrace(); }
try {
if(myArrayListwr.size()!=0)
{
System.out.println("inside on back pressed saving data to lineswr");
//Modes: MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITABLE
String fileNamewr = getApplicationContext().getFilesDir()+"/file/"+ "lineswr.txt";
FileOutputStream outputwr = openFileOutput("lineswr.txt",MODE_PRIVATE);
DataOutputStream doutwr = new DataOutputStream(outputwr);
doutwr.writeInt(myArrayListwr.size()); // Save line count
for(String linewr : myArrayListwr) // Save lines
doutwr.writeUTF(linewr);
doutwr.flush(); // Flush stream ...
doutwr.close(); // ... and close.
}
}
catch (IOException exc) { exc.printStackTrace(); }
Intent intent = new Intent(MainActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
}
}

Related

Android Studio Java display text file contents in new lines

Im creating a weight tracking app where the user inputs their weight clicks a save button and then the weight is saved. There is also a load button that loads all the previous inputs. The problem I'am having is that once load is clicked it does load up the weights on the screen but it does it all in one line other than a separate line for each.
I have checked the text file and all the weights are stored in a line each so there's no problem in the function that stores the inputs.
Here is the code for the `weight tracker
package com.example.workouttracker;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class WeightTracking extends AppCompatActivity {
private static final String FILE_NAME = "WeightTracking.txt";
EditText mEditText;
EditText mEditText2;
private Button button_back_home;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weight_tracking);
mEditText = findViewById(R.id.weight);
mEditText2 = findViewById(R.id.weight2);
button_back_home=(Button) findViewById(R.id.button_back_home);
button_back_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
homePage();
}
private void homePage(){
startActivity(new Intent(getApplicationContext(),MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
});
}
public void save(View v) {
String text = mEditText.getText().toString();
FileOutputStream fos = null;
try {
fos = openFileOutput(FILE_NAME, MODE_APPEND);
fos.write((text + "kg's\n").getBytes());
mEditText.getText().clear();
Toast.makeText(this, "Saved to " + getFilesDir() + "/" + FILE_NAME,
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void load(View v) {
FileInputStream fis = null;
try {
fis = openFileInput(FILE_NAME);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String text;
while ((text = br.readLine()) != null) {
sb.append(text);
sb.append('\n');
}
mEditText2.setText(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Someone know's how to get it to load each weight line by line?
Thanks
`
can you please check your xml file, if you have added property android:inputType="textMultiLine" on the edittext
Try changing your code like this:
String sb = "";
String text;
while ((text = br.readLine()) != null) {
sb = sb + text + "\n";
}

ProgressDialog cannot show when put ProgressDialog.dismiss method

ProgressDialog cannot show when i add progressDialog.dismiss() method on my code
I also try to add Thread.sleep() so that it execution will sleep for some time which can show progressdialog for some time but this will also not work.
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.os.Environment;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class Extraction {
ProgressDialog progressDialog;
public Extraction(List<ResolveInfo> apps, String publicSourceDir, String apkname, Context context) {
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Extracting");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setIndeterminate(true);
progressDialog.show();
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
File file = new File(publicSourceDir);
File file1 = new File(Environment.getExternalStorageDirectory().toString() + "/Extracted APK");
if (!file1.exists())
file1.mkdirs();
file1 = new File(file1.getPath() + "/" + apkname + ".apk");
if (!file1.exists())
file1.createNewFile();
bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file1));
byte[] buf = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buf)) > 0) {
bufferedOutputStream.write(buf, 0, len);
}
Thread.sleep(1000);
progressDialog.dismiss();
Toast.makeText(context, "Apk Extracted", Toast.LENGTH_LONG).show();
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
your need to put your long running work in a separate Thread or asyncTask
Because the UI is only updated at the end when your long running code is completed and then the show/dismiss is already called. thats why you only see the final result: a dismissed dialog
see the example (quoted from here:
Android: ProgressDialog doesn't show ):
Do something like:
public void doBackup(View view) throws IOException{
final ProgressDialog pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setMessage("Running backup. Do not unplug drive");
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
Thread mThread = new Thread() {
#Override
public void run() {
File source = new File("/mnt/extSdCard/DirectEnquiries");
File dest = new File("/mnt/UsbDriveA/Backup");
copyDirectory(source, dest);
pd.dismiss();
}
};
mThread.start();
}
and also here:
ProgressDialog not showing while performing a task

FileOutputStream are not working

I made an android app for learning Java.
Now i like to write objects from a list with objects to a file.
like ...
private List<MyObjects> objects = new ArrayList<MyObjects>();
MyObjects is a extra class and implements "Serializable".
To write the objects in a file i use also a extra class.
Now my problem.
With the below Line i get a FileNotFoundException.
fos = new FileOutputStream(fileName);
When i change this Line with this Line ...
fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
... looks like good but after endig the code i can't find the file in data/data/myPakage/files/.
The file is not exist.
I read the last 4 days a lot of sites and tutorials about that but i can't find my mistake.
Please help my.
I don't need a solved code but a link to the right side or a pointer in my mistaken code is fine.
Sorry for my english. Is not my first language.
I am not sure with code parts you need to get a good overview. If you need more, please tell me.
Here parts of my main site
package com.example.myProject;
import android.os.Bundle;
import android.app.FragmentTransaction;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
public class ActivityMain extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout_calc);
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
}
}
Here parts of my fragment site
package com.example.myProject;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment_1 extends Fragment implements OnClickListener {
private Button btnOFF;
private List<Numbers> number = new ArrayList<Numbers>();
private View fragment_1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.fragment_1 = inflater.inflate(R.layout.fragment_layout, container, false);
this.btnOFF = (Button)elementary.findViewById(R.id.id_btnOFF_Elementary);
this.btnOFF.setOnClickListener(this);
this.number.add(new Numbers());
// Here i try to get my data back from the file.
// Every time i get the information; The file not exist
// Perhaps the "containsAll" are wrong. But this is in the moment not my problem.
this.number.containsAll(StreamControl.importNumbers(this.getActivity()));
return fragment_1;
}
#Override
public void onClick(View buttonView) {
if (buttonView == this.btnOFF) {
// Here i try to export data over extra class -- see below
// I put in my List with objects calls "number" and information
// for "Context" i hope.
StreamControl.exportNumbers(number, this.getActivity());
}
}
}
Parts of my class Numbers
package com.example.myProject;
import java.io.Serializable;
public class Numbers implements Serializable {
private static final long serialVersionUID = -5384438724532423282L;
.
.
.
}
Here the code from the file "in" and "out"
package com.example.myProject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
public class StreamControl {
public static void exportNumbers(List<Numbers> number, Context ctx) {
String fileName = "MyCacheFile.ser";
File cacheFile = new File(fileName);
FileOutputStream fos = null;
try {
// With this line is it not working everytime.
// File not found exception
// But to make my own file with "createNewFile()" is not working
// in data/data i have just read permission.
fos = new FileOutputStream(cacheFile);
// If i use this line i have less problems.
// All Informations "i used Toast on a lot of places" was god.
// But after it, it was nowhere a file to found.
//fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(fos);
oos.writeInt(number.size());
for (int i =0; i < number.size(); i++) {
oos.writeObject(new Numbers(((Numbers)number.get(i)).getNumbers()));
}
}
catch (IOException e1) { e1.printStackTrace(); }
finally {
try {
if (oos != null) { oos.close(); }
}
catch (IOException ex) { }
}
}
catch (FileNotFoundException e2) { e2.printStackTrace(); }
finally {
try {
if (fos != null) { fos.close(); }
}
catch (IOException ex) { ex.printStackTrace(); }
}
}
public static List<Numbers> importNumbers(Context ctx) {
String fileName = "MyCacheFile.ser";
int count = 0;
List<Numbers> number = new ArrayList<Numbers>();
FileInputStream fis = null;
try {
fis = new FileInputStream(fileName);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(fis);
count = ois.readInt();
for (int i = 0; i < count; i++) {
number.add(new Numbers(((Numbers) ois.readObject()).getNumbers()));
}
}
catch (IOException ex) { ex.printStackTrace(); }
catch (ClassNotFoundException ex) { ex.printStackTrace(); }
finally {
try {
if (ois != null) { ois.close(); }
}
catch (IOException ex) { ex.printStackTrace(); }
}
}
catch (FileNotFoundException ex) { ex.printStackTrace(); }
finally {
try {
if (fis != null) { fis.close(); }
}
catch (IOException ex) { ex.printStackTrace(); }
}
return number;
}
}
So, i hope that's are enough information.
I looking forward
When you use Context.openFileOutput you create a file in internal storage and you can't check that directory.
Take a look at this to save a file to external storage

Saving Data from multiple inputs to file

I am developing an android application where the user has to enter text into multiple 'edittext' boxes and then i am trying to take the entered data and save it to a text file. I have got my application to save the data from the first few boxes. I have tried many approaches such as using a for loop and others but it still doesn't work. I'm currently using an array list by adding the first few bits of data to the list, writing it to the text file, clearing the list then adding the rest of the data and trying to append that to the file.
In debugging the application gets as far as adding the first bit of the new data and stops, without crashing or any errors.
This is my code:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener{
private Button submitForm,resetForm,btnEmail;
private String saveName;
private EditText name,depot,date,time,location,details,outcome,did;
private String attachedPathFile;
private File folder;
File myFile;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//StrictMode.enableDefaults();
name = (EditText)findViewById(R.id.nameText);
depot = (EditText)findViewById(R.id.DepotText);
date = (EditText)findViewById(R.id.DateText);
time = (EditText)findViewById(R.id.LocationText);
details = (EditText)findViewById(R.id.IncidentText);
outcome = (EditText)findViewById(R.id.OutcomeText);
did = (EditText)findViewById(R.id.DetailsText);
submitForm = (Button)findViewById(R.id.SubmitButton);
submitForm.setOnClickListener(new OnClickListener(){
#SuppressLint("SimpleDateFormat")
public void onClick(View v) {
// write on SD card file data in the text box
try {
folder = new File(Environment.getExternalStorageDirectory(),"Close Call Reports");
folder.mkdirs();
saveName = new SimpleDateFormat("yyyy-MM-dd HH mm ss").format(new Date());
myFile = new File(Environment.getExternalStorageDirectory().toString()+"/Close Call Reports/"+saveName+".txt");
myFile.createNewFile();
// FileOutputStream fOut = new FileOutputStream(myFile, true);
// OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
//
// //gets text data to write to file
// String data = "Your Name: "+name.getText().toString()+"\n"+"Your Depot: "+depot.getText().toString()+"\n"+"Date: "+
// date.getText().toString()+"\n"+"Time: "+time.getText().toString()+"\n";
// String data2 ="Location: "+location.getText().toString()+
// "\n"+ "Incident: "+details.getText().toString()+"\n"+"Potential Outcome: "+outcome.getText().toString()+"\n"+
// "What did you do ? "+did.getText().toString();
List<String> data = new ArrayList<String>();
data.add("Your Name: "+name.getText().toString());
data.add("Your Depot: "+depot.getText().toString());
data.add("Date: "+date.getText().toString());
data.add("Time: "+time.getText().toString());
appendToFile(data);
data.clear();
Log.v("DEBUGGING", "got here 1");
//data = new ArrayList<String>();
data.add("Location: "+location.getText().toString());
data.add("Incident: "+details.getText().toString());
data.add("Potential Outcome: "+outcome.getText().toString());
data.add("What did you do ? "+did.getText().toString());
Log.v("DEBUGGING", "got here 2");
appendToFile(data);
Log.v("DEBUGGING", "got here 3");
// myOutWriter.append(data);
// myOutWriter.close();
// fOut.close();
// Toast.makeText(getBaseContext(),
// "Done writing Comment File",
// Toast.LENGTH_SHORT).show();
name.setText("");
depot.setText("");
date.setText("");
time.setText("");
location.setText("");
details.setText("");
outcome.setText("");
did.setText("");
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
// write on SD card file data in the text box
}// onClick
}); // btnWriteSDFile
btnEmail = (Button)findViewById(R.id.Emailbtn);
btnEmail.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
String[] emailTo = new String[]{"ameyandroidapp#gmail.com"};
String subject = "Close Call Reporting";
String [] filePaths= new String[1];
//if(filePaths[0]==null){
for(int a=0; a < filePaths.length;a++){
attachedPathFile = Environment.getExternalStorageDirectory().toString()+"/Close Call Reports/"+saveName+".csv";
//path+ls+saveName+"("+a+")"+".txt";
filePaths[a] = attachedPathFile;
}
sendEmail(emailTo,subject,filePaths);
// }else{
// Toast.makeText(getBaseContext(),"No Files To Email",Toast.LENGTH_LONG).show();
//}
}
});
resetForm = (Button)findViewById(R.id.ResetButton);
resetForm.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
name.setText("");
depot.setText("");
date.setText("");
time.setText("");
location.setText("");
details.setText("");
outcome.setText("");
did.setText("");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void sendEmail(String[] emailTo, String subject,
String[] filePaths) {
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
emailIntent.setData(Uri.parse("mailto: "));
emailIntent.putExtra(Intent.EXTRA_EMAIL, emailTo);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.setType("message/rfc822");
ArrayList<Uri> uris = new ArrayList<Uri>();
for(String file: filePaths){
File fileIn = new File(file);
Uri u = Uri.fromFile(fileIn);
uris.add(u);
}
//emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM,uris);
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, uris);
startActivity(Intent.createChooser(emailIntent, "Email"));
}
#Override
public void onClick(View v) {
}
public void appendToFile (List<String> SarrayList) {
BufferedWriter bw = null;
boolean myappend = true;
try {
bw = new BufferedWriter(new FileWriter(myFile, myappend));
for(String line: SarrayList ) {
bw.write(line);
bw.newLine();
}
bw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (bw != null) try {
bw.close();
} catch (IOException ioe2) {
// ignore it or write notice
}
}
}
}
I'm surprised you're not seeing it crash, as it looks to me like you should be getting a NullPointerException as you don't seem to be setting the value of location. Also, it looks wrong that you're setting the value of time using the view with ID R.id.LocationText:
time = (EditText)findViewById(R.id.LocationText);
but it's difficult to be sure without knowing what you're doing exactly.

Input/Output between C binary and Java on Android

I need to grab text questions from C binary and display it in my TextView. Also, I need to grab an answers from input field and pass it to C binary, etc. I read this topic and tried to run it on Android. C binary works in shell, but my app doesn't work (blank screen). I am very new in Java and I need help.
package com.example.helloapp;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class HelloApp extends Activity
{
private Button btn;
private EditText editText;
private TextView textView;
private BlockingQueue<String> m_queue;
private BufferedReader bufIn;
private InputStream in;
private InputThread inputThread;
private PrintWriter printOut;
private Process p;
private Handler handler;
private String input = null;
// show nice popup on error
private void popup(String msg)
{
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
HelloApp.this.finish();
}
};
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView)findViewById(R.id.textView1);
btn = (Button)findViewById(R.id.button1);
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
// new Thread cannot change our TextView, so we use Handler
handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
String text = (String) msg.obj;
textView.setText(text);
}
};
File f = new File(getCacheDir()+"/hello");
if(!f.exists())
try {
// unpack our binary...
InputStream is = getAssets().open("hello");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
// ... and make it executable
try {
Process chmod = Runtime.getRuntime().exec("/system/bin/chmod 777 " +f.getPath());
chmod.waitFor();
} catch(IOException e) { popup(e.getMessage()); } catch(InterruptedException e) { popup(e.getMessage()); }
} catch(IOException e) { popup(e.getMessage()); }
try {
p = Runtime.getRuntime().exec(f.getPath());
InputStream in = p.getInputStream() ;
OutputStream out = p.getOutputStream ();
InputStream err = p.getErrorStream();
printOut = new PrintWriter(out);
m_queue = new ArrayBlockingQueue<String>(10);
inputThread = new InputThread(in, m_queue);
inputThread.start();
} catch(Exception e) { popup(e.getMessage()); }
btn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
editText = (EditText)findViewById(R.id.editText1);
input = editText.getText().toString();
// pass something to C binary
printOut.println(input+"\n");
printOut.flush();
}
});
}
private void setTextHandler(final String text)
{
Message msg = new Message();
msg.obj = text;
handler.sendMessage(msg);
}
private void mainLoop()
{
String line;
while(true)
{
try {
line = bufIn.readLine();
// stdin is always empty... why?
if(line != null) { setTextHandler(line); }
}
catch(IOException e) { popup(e.getMessage()); return; }
}
}
private class InputThread extends Thread
{
InputThread(InputStream in, BlockingQueue<String> queue)
{
bufIn = new BufferedReader(new InputStreamReader(in));
m_queue = queue;
}
public void run() {
try { mainLoop(); }
catch(Throwable t) { popup(t.getMessage()); }
}
}
}
UPDATE: if I compile the following C code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s;
setvbuf(stdout, NULL, _IONBF, 0); // <<<= disable buffering globally
printf("Enter your name:\n");
fflush(stdout);
scanf("%s", &s);
printf("Hello, %s", s);
fflush(stdout);
return 0;
}
I get results only when binary exits, ie. I run android app, see a blank screen (must see "Enter your name:"), input something, press OK button - binary exits and I get "Enter your name: Hello, Eugene" at once.
PROBLEM SOLVED! See updated C code.

Categories

Resources