Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自己動手做一個adb的wifi連接及adb命令的apk

自己動手做一個adb的wifi連接及adb命令的apk

編輯:關於Android編程

前言

估計搞安卓開發的小伙伴們都放棄了eclipse的開發轉戰android studio了吧,現在gradle都3.0 buiild都24.0.2了以後 都不再支持2.2及以下的版本了。eclipse的同學快上車。

上面的都不是重點,每當你大清早起來去公司上班,然後打開電腦發現你的usb線沒有帶,作為一個安卓程序員的你有點尴尬了。

然後你果斷的給android studio裝上ADB WIFI插件,哈哈,事實證明你還是相當的機智,然後你會面臨另外一個尴尬(蛋疼)。你使用時會出現如圖:

\

你會蛋微涼微涼的,這特麼不是說好的可以用wifi連接adb嗎?寶寶心裡苦但是不能哭,問題來了你該找誰借usb線呢?特麼安卓程序員都要自己用,所以你果斷放棄找他們了,然後去找測試妹子嗎感覺也有點不好。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxibG9ja3F1b3RlPg0KCTxwPtfuuvPE2MTjv8nE3Lvh0aHU8c/CuPZXaXJlbGVzc0FEQizIu7rzzai5/WNtZMP8we7AtMGsvdPK1rv6o6zIt8q10Ke5+7u5ysexyL3Pw/fP1KOsv8nS1MuzwPu1xM3qs8nIzs7xo6zH88jLsrvI58fzvLq21LDJoaM8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8cD48aW1nIGFsdD0="這裡寫圖片描述" src="/uploadfile/Collfiles/20160822/20160822094245930.jpg" title="\" />

這樣手機就連接起來了,寶寶再也不再擔心手機忘記帶數據線連接不起wifi了。但是用別人的還是不爽,今天寶寶就自己來實現這個功能(記住這功能要操作adb那麼你的手機必須是root的,手機沒有root你還做個毛的安卓程序員)。

實現效果

就不用gif來展示了,搞2個圖來展示下效果圖算了:

這裡寫圖片描述
這裡寫圖片描述

這裡寫圖片描述

動手實現思路

代碼獲取局域網ip地址

判斷手機是否獲取root權限(su),沒有自行root(不會的話jj剁了)

su文件寫入adb 命令執行相關的操作

cmd執行連接命令,win可以寫個bat文件


所有的步驟就上面這些了,開始果斷撸碼吧。


然後具體的就是先判斷是否有root,畢竟adb是需要root的,然後也就是把命令寫入su文件執行。(也可以通過Android Runtime來弄,更加輕松)

Android Runtime使得直接調用底層Linux下的可執行程序或腳本成為可能

比如Linux下寫個測試工具,直接編譯後apk中通過Runtime來調用

或者寫個腳本,apk中直接調用,省去中間層或者JNI

需要注意:

exec不等於console命令

2.exec的輸入輸出流需要自己處理

3.exec執行時阻塞、非阻塞,返回結果問題

4.注意權限問題

開始撸

獲取ip地址(先得有一個局域網wifi)

 /**
     * @return 獲取ip地址
     */
    public static String getIpAddress() {
        try {
            for (Enumeration en = NetworkInterface
                    .getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration enumIpAddr = intf
                        .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()
                            && inetAddress instanceof Inet4Address) {

                        return inetAddress.getHostAddress().toString();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

把32位整形的ip地址換成“...”地址

我們先通過安卓裡面的WifiManager來獲取wifiInfo,接著通過wifiInfo使用aidl來獲取32位整形的ip地址,接著我們把它轉化為我們常見的ip地址形式

 /**
     * @return 獲取局域網的ip地址形式(32位整型IP地址轉成本地ip)
     */
    private static String getLocalIpAddress() {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        // 獲取32位整型IP地址
        int ipAddress = wifiInfo.getIpAddress();
        // 返回整型地址轉換成“*.*.*.*”地址
        return String.format("%d.%d.%d.%d", (ipAddress & 0xff),
                (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
                (ipAddress >> 24 & 0xff));
    }

准備工作已經做好了(適配獲取局域網ip)。

獲取判斷root權限

Runtime.getRuntime().exec("su");

一般我們使用adb得先去獲取root權限的,也就是檢驗是否有su文件。

 // 判斷機器Android是否已經root,即是否獲取root權限
    public boolean haveRoot() {
        if (!mHaveRoot) {
            int ret = execRootCmdCilent("echo test"); // 通過執行測試命令來檢測
            if (ret != -1) {

                Toast.makeText(context, "已經root", Toast.LENGTH_LONG).show();
                mHaveRoot = true;
            } else {
                Toast.makeText(context, "not root", Toast.LENGTH_LONG).show();
                Log.i(TAG, "not root!");
            }
        } else {
            Toast.makeText(context, "已經root", Toast.LENGTH_LONG).show();
            Log.i(TAG, "mHaveRoot = true, have root!");
        }
        return mHaveRoot;
    }

設置adb服務連接的ip和端口,並且開啟adb

 /**
     * 打開adb連接
     *
     * @param tv
     */
    public static void openAdb(TextView tv) {
        if (!isConn) {
            tv.setText(" adb connect" + getLocalIpAddress());
            execShell("setprop service.adb.tcp.port 8888");//  Runtime.getRuntime().exec(new String[]{"/system/bin/su","-c", "setprop service.adb.tcp.port 5555"});
            try {

                Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "start adbd"}); //   execShell("start adbd");
            } catch (IOException e) {
                e.printStackTrace();
            }
            isConn = true;

        }
    }

其實呢,看代碼我們也知道我們既可以使用用寫入su文件的方式也可以直接使用Runtime.getRuntime().exec()來執行,後文全部使用後者使用起來很簡單。

  /**
     * 在su文件中寫入命令
     *
     * @param str
     */
    public static void execShell(String str) {
        try {
            // 權限設置
            Process p = Runtime.getRuntime().exec("su");
            // 獲取輸出流
            OutputStream outputStream = p.getOutputStream();
            DataOutputStream dataOutputStream = new DataOutputStream(
                    outputStream);
            // 將命令寫入
            dataOutputStream.writeBytes(str);
            // 提交命令
            dataOutputStream.flush();
            // 關閉流操作
            dataOutputStream.close();
            outputStream.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

上面貼的代碼和Runtime.getRuntime().exec(cmdstr)的功能一樣。

連接的時候,你需要在cmd敲命令adb connect 你的ip地址,當然一般你是配置了adb的環境的,win下所以你只需要寫一個bat文件就好了,連接的時候點擊下。

\

裡面的內容,你只需要把cmd命令拷貝進去好了(ip不能經常變的前提,變了手動改)。

關閉adb

/**
     * 斷開adb連接
     */
    public static void closeAdb() {
        try {
            Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "stop adbd"});
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

重啟adb

  /**
     * 重啟adb
     */
    public static void restartAdb() {
        try {
            Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "adb kill-server"});
            Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "adb start-server"});
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

根據包名卸載apk

  /**
     * 卸載apk
     */
    public static void uninstallApk(String packageName) {
        try {
            Process p= Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "pm uninstall " + packageName});
            if (p == null) {
                Toast.makeText(context, "app 卸載失敗", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(context, "app 已成功卸載", Toast.LENGTH_LONG).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

根據包名殺死apk(好像沒有效果)

  /**
     * 殺死app
     *
     * @param packageName 包名
     */
    public static void killApp(String packageName) {
        try {
            Process p=Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", " am force-stop " + packageName});

            if (p == null) {
                Toast.makeText(context, "app 關閉失敗", Toast.LENGTH_LONG).show();
            } else {

                Toast.makeText(context, "app  關閉成功", Toast.LENGTH_LONG).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

殺死當前應用

 /**
     * 通過Android底層實現關閉當前進程
     */
    public  static void killProcess() {
        int pid = android.os.Process.myPid();
        if (pid != 0) {
                System.exit(0);
                android.os.Process.killProcess(pid);
        }
    }

開啟指定app(須知道包名)

 /**
     * 打開apk
     *
     * @param packageName
     */
    public static void startApk(String packageName) {

            try{
                Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
                context.startActivity(intent);
            }catch(Exception e){
                Toast.makeText(context, "沒有安裝", Toast.LENGTH_LONG).show();
            }

    }

清除指定apk數據

 /**
     * 清除apk緩存
     *
     * @param packageName
     */
    public static void clearApp(String packageName) {
        try {
        Process p= Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "pm clear " + packageName + " HERE"});
            if (p == null) {
                Toast.makeText(context, "app 緩存數據清空失敗", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(context, "app  緩存數據清空成功", Toast.LENGTH_LONG).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

adb命令重啟

    /**
     * 重啟手機
     */
    public static void rebootPhone() {
        try {
            Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "reboot"});
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

adb 命令關機

  /**
     * 關閉手機
     */
    public static void closePhone() {
        try {
            Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", "reboot -p"});
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

具體使用代碼很簡單:

package com.losileeya.wifiadb;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv_conn_adb)
    TextView tvConnAdb;
    @BindView(R.id.tv_conn_stop)
    TextView tvConnStop;
    @BindView(R.id.tv_adb_restart)
    TextView tvAdbRestart;
    @BindView(R.id.et_appinfo)
    EditText etAppinfo;
    @BindView(R.id.tv_uninstall_app)
    TextView tvUninstallApp;
    @BindView(R.id.tv_kill_app)
    TextView tvKillApp;
    @BindView(R.id.tv_start_app)
    TextView tvStartApp;
    @BindView(R.id.tv_clean_appdata)
    TextView tvCleanAppdata;
    @BindView(R.id.tv_close_phone)
    TextView tvClosePhone;
    @BindView(R.id.tv_rebot_phone)
    TextView tvRebotPhone;
    @BindView(R.id.tv_kill_currentapp)
    TextView tvKillCurrentapp;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

    @OnClick({R.id.tv_conn_adb, R.id.tv_conn_stop, R.id.tv_adb_restart, R.id.tv_uninstall_app, R.id.tv_kill_app,R.id.tv_kill_currentapp, R.id.tv_start_app, R.id.tv_clean_appdata,R.id.tv_rebot_phone,R.id.tv_close_phone})
    public void onClick(View view) {
     String packageName=etAppinfo.getText().toString().trim();
        switch (view.getId()) {
            case R.id.tv_conn_adb:
                Intent intent= new Intent(MainActivity.this,ConnectActivity.class);
                intent.putExtra("isConn",true);
                startActivity(intent);
                break;
            case R.id.tv_conn_stop:
                Intent i= new Intent(MainActivity.this,ConnectActivity.class);
                i.putExtra("isConn",false);
                startActivity(i);
                break;
            case R.id.tv_adb_restart:
                new AdbUtil(this).restartAdb();
                break;
            case R.id.tv_uninstall_app:
                if(TextUtils.isEmpty(packageName)){
                    Toast.makeText(this,"請輸入包名",Toast.LENGTH_SHORT).show();
                }else{
                new AdbUtil(this).uninstallApk(packageName);
                }
                break;
            case R.id.tv_kill_app:
                if(TextUtils.isEmpty(packageName)){
                    Toast.makeText(this,"請輸入包名",Toast.LENGTH_SHORT).show();
                }else {
                    new AdbUtil(this).killApp(packageName);

                }
                break;
            case R.id.tv_kill_currentapp:

                new AdbUtil(this).killProcess();
                break;
            case R.id.tv_start_app:
                if(TextUtils.isEmpty(packageName)){
                    Toast.makeText(this,"請輸入包名",Toast.LENGTH_SHORT).show();
                }else {
                    new AdbUtil(this).startApk(packageName);
                }
                break;

            case R.id.tv_clean_appdata:
                if(TextUtils.isEmpty(packageName)){
                    Toast.makeText(this,"請輸入包名",Toast.LENGTH_SHORT).show();
                }else {
                    new AdbUtil(this).clearApp(packageName);
                }
                break;
            case R.id.tv_close_phone:
               new AdbUtil(this).closePhone();
                break;
            case R.id.tv_rebot_phone:
                new AdbUtil(this).rebootPhone();
                break;
        }
    }
}

總結

代碼不難,就是為了學習一下adb命令,裝在手機裡沒有帶數據線的時候,也可以拿來進行wifi連接adb調試安卓應用以後再也不用去下載什麼WirelessAdb了,至少關機重啟還是方便點吧,可能跟cmd命令有點點差別吧。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved