Android应用程序执行shell指令(包含执行root指令)

因为项目需求需要在android的应用程序中去动态的执行预先放入手机中的一个程序,所以到处找了很多资料。虽然网上各种各样的东西不少,不过感觉多多少少都有点不够,折腾了半天之后终于满意了,记录整个过程。
要想执行su指令必须要求手机root。


相关的类

测试工程代码

代码功能

获取su权限,执行命令 “ls /data/data”(需要root才能访问/data/data)

MainActivity.java


import android.app.Activity;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class MainActivity extends Activity {

    private  final static String[] ARGS={"ls","-l"};
    private  final static String TAG="com.dd.test";
    Button mButton,rButton,cButton;
    TextView myTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton= (Button) findViewById(R.id.myButton);
        cButton = (Button) findViewById(R.id.clearB);
        myTextView= (TextView) findViewById(R.id.textView);

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myTextView.setText(getResult());
            }
        });
        cButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myTextView.setText("hello world");
            }
        });

    }

    public String getResult(){
        ShellExecute cmdexe=new ShellExecute();
        String result="";
        try{
            result=cmdexe.execute(ARGS,"/data/data/");
        }catch (Exception e){
            Log.e(TAG,"IOEXCEPTION");
            e.printStackTrace();
        }
        return result;
    }
    private class ShellExecute{
        public String execute (String[] command,String directory) throws IOException{
            String result="";
            String[] suC={"su"};
            try{

                ProcessBuilder builder= new ProcessBuilder(suC);
                if (directory!=null)
                    builder.directory(new File(directory));
                builder.redirectErrorStream(true);
                Process process=builder.start();
                DataOutputStream os;
                os=new DataOutputStream(process.getOutputStream());
                InputStream is= process.getInputStream();

                os.writeBytes( "ls\n");
                os.flush();
                os.close();
                byte[] buffer=new byte[1024];
                while (is.read(buffer)!=-1){
                    result=result+new String(buffer);
                }
                is.close();

            }catch (Exception e){
                e.printStackTrace();
            }
            return result;
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

activity_main.xml

<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="click"
            android:id="@+id/myButton"
            />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="clear"
            android:id="@+id/clearB"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="text..."
            android:id="@+id/textView"
            />
    </LinearLayout>
</RelativeLayout>

代码解释说明

布局文件就不多赘述了,很简单的一个布局

核心代码其实是

    private class ShellExecute{
        public String execute (String[] command,String directory) throws IOException{
            String result="";
            String[] suC={"su"};
            try{

                ProcessBuilder builder= new ProcessBuilder(suC);
                if (directory!=null)
                    builder.directory(new File(directory));
                builder.redirectErrorStream(true);
                Process process=builder.start();
                DataOutputStream os;
                os=new DataOutputStream(process.getOutputStream());
                InputStream is= process.getInputStream();

                os.writeBytes( "ls\n");
                os.flush();
                os.close();
                byte[] buffer=new byte[1024];
                while (is.read(buffer)!=-1){
                    result=result+new String(buffer);
                }
                is.close();

            }catch (Exception e){
                e.printStackTrace();
            }
            return result;
        }

    }

这里先是将su 这条指令作为参数传入ProcessBuilder,然后调用它的start() 方法,获取到一个process。
这里,其实已经相当于在adb shell中执行了一条su 的指令了。
在实际的应用运行的过程中,会提示“应用程序需要获取root权限”。
接下来比较重要的是DataOutputStreamInputStream
在android文档中写的


  • InputStream

    public abstract InputStream getInputStream ()
    Returns an input stream that is connected to the standard output stream (stdout) of the native process represented by this object.
    Returns
    the input stream to read from the output stream associated with the native process.

  • DataOutputStream

    public abstract OutputStream getOutputStream ()
    Returns an output stream that is connected to the standard input stream (stdin) of the native process represented by this object.
    Returns
    the output stream to write to the input stream associated with the native process.


可见,说直白点就是获取了一个shell的stdin和stdout,所以我们直接进行读写就相当于在shell中输入相关的命令并且获取对于的输出结果了。

一些参考文章

以下是一部分在网上查资料时看到的,权当记录
http://www.android-doc.com/reference/java/lang/Process.html
http://www.cnblogs.com/ycmoon/archive/2011/05/11/2042999.html?login=1
http://blog.csdn.net/y13872888163/article/details/6530430
http://www.open-open.com/lib/view/open1409190296025.html

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值