自己动手做一个adb的wifi连接及adb命令的apk
来源:互联网 发布:打谱软件overture下载 编辑:程序博客网 时间:2024/05/19 06:37
前言
估计搞安卓开发的小伙伴们都放弃了eclipse的开发转战android studio了吧,现在gradle都3.0 buiild都24.0.2了以后 都不再支持2.2及以下的版本了。eclipse的同学快上车。
上面的都不是重点,每当你大清早起来去公司上班,然后打开电脑发现你的usb线没有带,作为一个安卓程序员的你有点尴尬了。
然后你果断的给android studio装上ADB WIFI插件,哈哈,事实证明你还是相当的机智,然后你会面临另外一个尴尬(蛋疼)。你使用时会出现如图:
你会蛋微凉微凉的,这特么不是说好的可以用wifi连接adb吗?宝宝心里苦但是不能哭,问题来了你该找谁借usb线呢?特么安卓程序员都要自己用,所以你果断放弃找他们了,然后去找测试妹子吗感觉也有点不好。
最后呢你可能会选择下个WirelessADB,然后通过cmd命令来连接手机,确实效果还是比较明显,可以顺利的完成任务,求人不如求己对吧。
这样手机就连接起来了,宝宝再也不再担心手机忘记带数据线连接不起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<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); en.hasMoreElements(); ) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> 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; } }}
demo 传送门:WifiAdb.zip
总结
代码不难,就是为了学习一下adb命令,装在手机里没有带数据线的时候,也可以拿来进行wifi连接adb调试安卓应用以后再也不用去下载什么WirelessAdb了,至少关机重启还是方便点吧,可能跟cmd命令有点点差别吧。
- 自己动手做一个adb的wifi连接及adb命令的apk
- WIFI的ADB命令积累
- 常用adb 安装apk 的命令及区别
- ADB Tool的安装及ADB命令
- 简单的 adb shell 命令启动 apk
- adb命令和使用adb遇到的问题及解决
- 实用的adb 命令连接 android 电视
- 通过adb命令连接特定的设备
- adb通过wifi连接
- 用WiFi连接adb
- adb WiFi连接方法
- wifi连接adb
- WIFI adb 连接手机
- 用wifi连接adb
- 使用wifi连接adb
- 无需root简单易用安卓wifi调试 这个只是一个小操作,三步: 1. 用数据线连接你的手机和电脑 2. 电脑终端执行命令: adb tcpip 5555 3. 电脑终端执行命令: adb c
- 如何使用adb shell命令启动一个安装好的apk
- adb通过wifi连接android设备的方法
- Android实战之驱家新闻app(四)
- 【NOIP2012模拟10.29】排列 一题总结
- Jquery李炎恢——35概述及jQuery UI[1]
- HDU 5863 cjj's string game 快速幂 dp
- Java日期时间
- 自己动手做一个adb的wifi连接及adb命令的apk
- Java8语法和新功能
- mv遇到空格和小括号文件引发的问题
- Codeforces Round #368 (Div. 2)C.Pythagorean Triples 本原勾股数组
- JDK---API文档
- Java正则表达式实例教程
- Java多线程编程教程
- linuxshell --sed 常用指南
- Java JDBC连接各种数据库实例