0

Im still very new to Android development, so I apologize in advance if my question seems silly.

In my application I have one button. When the button is clicked it attempts to see if the application has its own folder on the internal storage, if not it creates a folder, then it creates a file called output.txt, then it writes system information to the output.txt, then it attempts to write all lines containing "SIP_MESSAGE" from the logcat into the output.txt, it then emails the default email address.


EDIT

After a few days of toiling I managed to put it all together. Please read the answer below for everything in detail.

Nefariis
  • 3,451
  • 10
  • 34
  • 52
  • 1
    You're reading from the logcat right... how many lines in there? – t0mm13b Jan 23 '13 at 01:07
  • The number of lines reading in from logcat could be the bottleneck there, and thus appears "hanging" as the logcat is constantly getting spammed, not just by your app, but by Android as a whole! – t0mm13b Jan 23 '13 at 01:51
  • Hmm, it appears that you are right, this is where the application is hanging... I know the logcat is a buffer of memory that can only get to a certain size, fifo if you will. Is there anyway to save the logcat, from the beginning of the buffer up to when the button is clicked? – Nefariis Jan 23 '13 at 20:04

4 Answers4

1

After a few days of research and a countless number of guess and checks, I finally figured everything out. I want to take this time to actually explain everything, in case anyone comes across this and is having the same problems that I had. Hopefully everything you are looking for is right here, and I gave a better explanation then the 100's of other sites that you (and I) had visited previous to this.

First topic is the difference between internal and external storage (it's not the difference between sdcard and not sdcard).

Internal storage is something that no one can see or get to but your application. If you create a file or folder on the internal storage, you cant use a file browser (unless your rooted) or your computer to see what you've created, it is completely inaccessible from outside your application.

Public folders such as Documents/Downloads/Music/Ringtones/etc. are technically on you external storage. You need permissions to write and read from it. This is where I was getting confused. I thought only sdcards counted as external storage, external storage is something you can manually get to from a computer or file browser whether its on an sdcard or not.

To create a file on the internal or external storage you do not need to use mkDir(). Anyone that says you do, is overly complicating things. You can actually create any text file anywhere on the system just from the code:

PrintWriter osw = new PrintWriter(Environment.getExternalStoragePublicDirectory(DOWNLOAD_SERVICE).toString() + "/output.txt");

This creates a text file in the download directory, whether it existed there or not first. You can also use getDataDirectory() or wherever else you want to create the file.

Next Logcat, like what the other people were pointing out, I was trying to read from the logcat as it was being created. There is no end to the logcat, so in effect, my application hung because it was constantly looking for more to write. An easy way around this is to use the -d feature of logcat. What that does is it just takes everything up to the point where -d was entered (which was exactly what I wanted), then it stops, then you can put it into a buffer and get the output with no hanging.

Finally, attaching a file to an email intent. This one was tricky because there were a few different areas that ended up giving me problems. In short, if you are receiving the error, "Couldn't show attachment", it means one of two things - 1.) you are trying to attach a file from the internal memory (remember, no other programs are allowed to access the internal memory, even gmail) or 2.) you are not using getAbsolutePath(). I found quite a few people that said you can't attach a file using uri.parse() and the you have to use uri.fromFile(), that is wrong, attached I show you how to attach a file and not get an error.

I hope this code helps you, and I hope you do not spend 1/10th of the time I did trying to figure this stuff out.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Calendar;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button mailb = (Button)findViewById(R.id.bmail);
    final TextView confirmation = (TextView)findViewById(R.id.Confirmation);
    mailb.setOnClickListener(new View.OnClickListener() {   
    @Override

    public void onClick(View v) {
        try {     
            PrintWriter osw = new PrintWriter(Environment.getExternalStoragePublicDirectory(DOWNLOAD_SERVICE).toString() + "/output.txt"); //This creates a file in my public download directory
               osw.println("Output Log: Report Tool");
               osw.println("Date: " + java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime())); 
               osw.println("------------------------------------");
               osw.println("Manufacturer: " + android.os.Build.MANUFACTURER);
               osw.println("Model: " + android.os.Build.MODEL);
               osw.println("Serial: " + android.os.Build.SERIAL);
               osw.println("BootLoader: " + android.os.Build.BOOTLOADER);
               osw.println("Build ID: " + android.os.Build.FINGERPRINT);
               osw.println("------------------------------------");
              try { 
                  Process p = Runtime.getRuntime().exec("logcat -d -v long"); //This gets the dump of everything up to the button press
                  BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                  String line = null;
                  while ((line = reader.readLine()) != null) {
                    if(line.toString().contains("SIP_MESSAGE")){ //This parses out everything but SIP Messages
                    osw.println(line); }}}
              catch (IOException e1) {confirmation.setText(e1.getMessage()); }

               osw.flush();
               osw.close();

        } catch(Exception e){ confirmation.setText(e.getMessage()); }

        String attach = Environment.getExternalStoragePublicDirectory(DOWNLOAD_SERVICE).getAbsolutePath() + "/output.txt"; //This is where you need to use the absolute path!!
        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("message/rfc822");
        i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"MyEmail@Email.com"});
        i.putExtra(Intent.EXTRA_SUBJECT, "Error Report.");
        i.putExtra(Intent.EXTRA_TEXT   , "Please see the attached file...");
        i.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + attach)); //This is where you attach the file 
        try {
            startActivity(Intent.createChooser(i, "Send mail..."));}
        catch (android.content.ActivityNotFoundException ex) {
            confirmation.setText("There is no Email Client installed on this device.");}                
    }
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

}    

And finally, the permissions I used for this was READ_LOGS, WRITE_EXTERNAL, READ_EXTERNAL.

I hope you've enjoyed, and good luck.

Nefariis
  • 3,451
  • 10
  • 34
  • 52
  • Good answer, I didnt know that gmail couldnt access your internal storage even if you passed in the absolute path. Are you sure about that? Nice tip about logcat too – Dheeraj Bhaskar Jan 25 '13 at 09:22
0

Oops! Spoke too soon, you meant internal.

Why don't you try writing a file directly into your app directory instead of creating a folder. Check if it that works first.

For that you may do:

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

This is what you're looking for:

File outputDir = new File(Environment.getExternalStorageDirectory()
            + "/farmer survey");
    outputDir.mkdirs();
    File outputFile = new File(outputDir, "something.csv");
    try {

        FileOutputStream fos = new FileOutputStream(outputFile);
        PrintWriter pw = new PrintWriter(fos);

        pw.println(text);
        pw.close();

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

You also need to add this permission:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Dheeraj Bhaskar
  • 18,633
  • 9
  • 63
  • 66
0

Do you have the android.permission.READ_LOGS permission in your manifest?

benkc
  • 3,292
  • 1
  • 28
  • 37
  • yes i do, it appears that it is contantly trying to read from the log instead of just the snap shot i was hoping for – Nefariis Jan 23 '13 at 20:28
0

For the email portion do you intent to send it automatically?

If so, I don't think it can be done in the background easily. The best is invoke the Gmail app with the output.txt attached as an attachment. Subsequently, you need to manually send it.

Otherwise the coding may be very long, see here:

Sending Email in Android using JavaMail API without using the default/built-in app

Or another way is to send out through SMS, this can be done in the background.

Community
  • 1
  • 1
aandroidtest
  • 1,493
  • 8
  • 41
  • 68
  • It doesnt send it automatically, it just invokes the GMail app from invoking Intent. Which is fine. – Nefariis Jan 23 '13 at 20:05