Asked  10 Months ago    Answers:  5   Viewed   7 times

I want to execute some shell commands and get the output in a TextView. The command may have a continuous output like ping or logcat. Also, the TextView should scroll automatically as the command output is added in real-time. In order to do so, I have done this:

package com.example.rootapp;

import java.io.DataOutputStream;
import java.io.InputStream;

import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;

public class MainActivity extends Activity {
    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String[] cmdArray={"logcat -b radio"};
        try {
            runAsRoot(cmdArray);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void runAsRoot(String[] cmds) throws Exception {
        tv=(TextView)findViewById(R.id.cmdOp);
        tv.setMovementMethod(new ScrollingMovementMethod());
        Process p = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(p.getOutputStream());
        InputStream is = p.getInputStream();
        for (String tmpCmd : cmds) {
            os.writeBytes(tmpCmd+"n");
            int readed = 0;
            byte[] buff = new byte[4096];
            boolean cmdRequiresAnOutput = true;
            if (cmdRequiresAnOutput) {
                while( is.available() <= 0) {
                    try { Thread.sleep(5000); } catch(Exception ex) {}
                }

                while( is.available() > 0) {
                    readed = is.read(buff);
                    if ( readed <= 0 ) break;
                    String seg = new String(buff,0,readed);   
                    tv.append(seg);
                }
            }
        }        
    }
}

This works fine, but it does not update the TextView continuously. As you can see, I'm executing radio logcat as root user, the output is generated continuously (already checked in terminal emulator and adb shell). But in my case, the output is not added continuously. It stops after a few 100 lines. Here is my layout:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/cmdOp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:text="@string/hello_world" />
</ScrollView>

</RelativeLayout>

The output should keep scrolling the TextView. At least this is what I expect...... Any workaround for this please?

 Answers

5

You can run command and display command output into text as below :

public class MainActivity extends Activity {

    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv=(TextView)findViewById(R.id.cmdOp);
        tv.setText("Output :"+"n"+runAsRoot());
    }

    public String runAsRoot() {

        try {
            // Executes the command.
            Process process = Runtime.getRuntime().exec("ls -l");

            // Reads stdout.
            // NOTE: You can write to stdin of the command using
            //       process.getOutputStream().
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));

            int read;
            char[] buffer = new char[4096];
            StringBuffer output = new StringBuffer();
            while ((read = reader.read(buffer)) > 0) {
                output.append(buffer, 0, read);
            }
            reader.close();

            // Waits for the command to finish.
            process.waitFor();

            return output.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Note : The "su" command does only run if the device is rooted. Otherwise it throws an exception.

Thursday, July 29, 2021
 
2

When using Eclipse, in the DDMS perspective, make sure the correct device (propably emulator-xxxx) is selected and highlighted. Only then will you get the logcat output in the logcat view.

Also, the Android plugin is a bit quircky, and sometimes only shows the last line in the logcat view. If this happens, try to clear the log. After that, you should get all the log entries again (works for me anyway).

Saturday, June 12, 2021
4

Edit: user1182474's comment is correct; Wine doesn't isolate the programs it runs. (It tries to hide it, but not very thoroughly.) I totally failed at using Google. Psen's comment below is more correct, and references the FAQ. (Note that, for that to work, you may need to have the program's directory available through a Wine drive mapping. Or, see Anonymous Replier's answer.)

== Old Answer ==

Wine isolates the programs it runs. The applications are, if all works as intended, presented with an environment indistinguishable from Windows. Unfortunately for your purposes, that means that you can't access the features of the host OS (Linux). I mean, you could patch Wine to do that, but I get the impression that it would be more work than it's worth.

There is hope! Cygwin is a Unix-like environment for Windows. You could install Cygwin in Wine, and use Cygwin to run your shell script. (Apparently, installing with 'winetricks cygwin' is easiest) Invoke Cygwin's bash shell (inside some Wine program) like this:

c:cygwinbinbash  myscript

Of course, change c:cygwin to wherever you install it.

Monday, August 9, 2021
 
5

OK, here are the results of a quick Google search:

  • Android Logging System
  • How to get kernel messages from Android?

What I got from those links are:

  1. The last part of your command should actually be cat /proc/kmsg
  2. logcat -v time -f /dev/kmsg writes logcat outputs to kernel message buffer

So,

logcat -v time -f /dev/kmsg | cat /proc/kmsg

will output both logcat and kernel logs to stdout (whatever it is). Probably, you may write the output to a file as follows:

logcat -v time -f /dev/kmsg | cat /proc/kmsg > /sdcard/log.txt

The above worked from adb shell prompt on a rooted Android 4.4.2 device.

Hope this helps.

Friday, October 15, 2021
 
cela
 
4

I would recommend you to use Sharedpreferences to store basic information, and read some tutorial or documentation about how to save data on Android. Here I made an example using Sharedpreferences. Hope it helps!

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

/**
 * Created by Hasan on 4.05.2017.
 */

public class ProfilActivity extends Activity {

    EditText editName, editNickname;
    Button bAddData;
    public SharedPreferences prefs;

    //To be saved elements in sharedpreferences!!!
    private String nicktobesaved, nametobesaved;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.activity_profil);
        prefs = getSharedPreferences("sharedPreferences", Context.MODE_PRIVATE);

        editName = (EditText) findViewById(R.id.name);
        editNickname = (EditText) findViewById(R.id.pseudo2);
        bAddData = (Button) findViewById(R.id.ajouter);

        //default values
        nametobesaved=prefs.getString("name", "");
        nicktobesaved=prefs.getString("nickname", "");

        bAddData.setEnabled(prefs.getBoolean("isEnabled", true) ? true : false);

        if(!nametobesaved.equals("")) {
            editName.setText(nametobesaved);
        }
        if (!nicktobesaved.equals("")){
            editNickname.setText(nicktobesaved);

        }

        AddData();
    } // End onCreate()

    public void AddData() { // When user click on bAddData button
        bAddData.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        nametobesaved=prefs.getString("name", "");
                        nicktobesaved=prefs.getString("nickname", "");

                        nametobesaved= editName.getText().toString();
                        nicktobesaved= editNickname.getText().toString();

                        if(nametobesaved.equals("") || nicktobesaved.equals("")){
                            Toast.makeText(ProfilActivity.this, "Fill all spaces", Toast.LENGTH_LONG).show();
                        }else {

                            SharedPreferences.Editor editor = prefs.edit();
                            editor.putString("name", nametobesaved);
                            editor.putString("nickname", nicktobesaved);
                            editor.commit();

                            Toast.makeText(ProfilActivity.this, "Data saved", Toast.LENGTH_LONG).show();
                            prefs.edit().putBoolean("isEnabled", false).commit();


                            bAddData.setEnabled(false);
                        }

                    }
                }
        );
    }
}

After saving nickname to the Sharedpreferences you need to load it in Main activity. It goes like this:

public class MainActivity extends Activity {

public static final int PROFIL_REQ = 1;
public static final String PSEUDO="nickname";
TextView tv;
Button login;

    //Sharedpreferences and nick name variables
    private SharedPreferences prefs;
    private String nickname;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView)findViewById(R.id.pseudo);

            //Load or create sharedpreferences
        prefs = getSharedPreferences("sharedPreferences", Context.MODE_PRIVATE);
        nickname = prefs.getString("nickname", "");

        if(nickname.equals("")) {
            tv.setText("Welcome");
        }else{
            tv.setText("Welcome "+ nickname);
        }
    }

That's because you deleted sharedpreferences editor.

public void AddData() { // When user click on bAddData button
    bAddData.setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    nicktobesaved = prefs.getString("nickname", "");
                    nicktobesaved = editPseudo.getText().toString();


//DO NOT DELETE HERE

                                    SharedPreferences.Editor editor = prefs.edit();

                                editor.putString("nickname", nicktobesaved);
                                editor.commit();

// The following code is just for save data on my database SQLite
                    boolean isInserted = myDb.insertData(editNickname.getText().toString());
                    if (isInserted == true) {
                        Toast.makeText(ProfilActivity.this, "Data saved", Toast.LENGTH_LONG).show();
                        prefs.edit().putBoolean("isEnabled", false).apply();
                        bAddData.setEnabled(false);
                    } else {
                        Toast.makeText(ProfilActivity.this, "Data not saved", Toast.LENGTH_LONG).show();
                    }
                }
            }
    );
}
Tuesday, December 7, 2021
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :