Ошибка сломанной трубы при выполнении метода Android более одного раза?

Я пытаюсь выполнить следующий метод, чтобы подделать MAC-адрес устройства Android. Метод запускается каждый раз, когда пользователь нажимает кнопку:

public void changeMac(View v) throws IOException {
        editText = (EditText)findViewById(R.id.newMacText);
        String mac = editText.getText().toString();
        Log.d("my log", "" + mac);
        String[] cmds = {"ip link set wlan0 address " + mac};

        Log.d("my log", "in method");
        DataOutputStream os = new DataOutputStream(p.getOutputStream());
        for (String tmpCmd : cmds) {
            os.writeBytes(tmpCmd + "\n");
        }
        os.writeBytes("exit\n");
        os.flush();


        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(p.getInputStream()));

        StringBuilder result = new StringBuilder();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            result.append(line);
        }

       Log.d("my log", "new mac " + Utils.getMACAddress("wlan0"));
        Log.d("my log", result.toString());

    }

Теперь, когда пользователь снова нажимает кнопку, приложение вылетает, и я получаю сообщение об ошибке «сломанная труба».

 android.system.ErrnoException: write failed: EPIPE (Broken pipe)

а также незаконное государственное исключение. Что я могу сделать, чтобы эта ошибка перестала возникать и чтобы метод вызывался несколько раз?


person coder4lyf    schedule 22.06.2015    source источник
comment
Как создать процесс, в который вы пишете (переменная p)? Я предполагаю, что это процесс root/su?   -  person Robert    schedule 22.06.2015
comment
да, я делаю процесс su p = Runtime.getRuntime().exec(su); в моем методе onCreate()   -  person coder4lyf    schedule 22.06.2015


Ответы (3)


Когда вы выполняете команду os.writeBytes("exit\n");, это завершает сеанс su. Процесс su завершается сам по себе, и канал, который вы используете для записи команд в оболочку su, ломается.

Поэтому, если вы хотите выполнить другую команду, вы должны перезапустить новую сессию su или не закрывать старую, вызвав exit.

В любом случае я бы не стал запускать процесс su в вашем методе onCreate(). Разрешения суперпользователя следует получать только при необходимости, а не при запуске приложения.

person Robert    schedule 22.06.2015
comment
Когда я удаляю строку os.writeBytes(exit\n); приложение зависает: / Если я каждый раз создаю новый сеанс su, будет ли оно каждый раз запрашивать у пользователя предоставление ему root-доступа? - person coder4lyf; 22.06.2015
comment
Конечно, он зависает, потому что цикл while, считывающий ввод, никогда не заканчивается. bufferedReader.readLine() возвращает null, если поток заканчивается (следовательно, если su завершился). Большинство пользователей постоянно разрешают root-права для приложения, если оно попросит. SuperSu имеет возможность ограничить разрешения до 10-15 минут, прежде чем снова запросит. Иногда появляется только небольшой Toast, сообщающий, что вашему приложению предоставлены root-права. - person Robert; 22.06.2015

Я сомневаюсь, что вы можете изменить MAC-адрес на любом устройстве.

Из википедии:

MAC-адреса чаще всего назначаются производителем контроллера сетевого интерфейса (NIC) и хранятся в его оборудовании, например в постоянной памяти карты или в каком-либо другом механизме встроенного ПО.

person Gordak    schedule 22.06.2015
comment
Это больше похоже на подмену MAC. - person coder4lyf; 22.06.2015

почему вы выполняете один и тот же код снова и снова, вы можете сохранить mac-адрес, запустив код один раз, как мы создаем сеанс, если вы меняете устройство, тогда в этом случае вам нужно снова проверить mac-адрес.

person Puneet Kumar    schedule 22.06.2015