出售本站【域名】【外链】

首页 AI人工智能软件 qqAI人工智能 微信AI人工智能 抖音AI人工智能 快手AI人工智能 云控系统 手机AI人工智能

Android 群控软件开发 android群控方案

2024-02-03

最近正在作一个分布式的AI智能云.要求手机端建议乞求,连贯到效劳器,通过效劳器打洞,连通控制端电脑.那样作的好处便是,任何人可以买几多十部手机就可以参预到那个网络,不须要原地电脑控制手机,简化了流程,勤俭了电脑的投入,最重要的是IP是结合的大大降低触发风控的几多率.那种控制形式类似于向日葵,TeamView端到实个控制.开发历程比较荆棘,记录一下开发思路以及逢到的坑

要真现那个工程,次要处置惩罚惩罚两个问题.

第一:选择一个成熟牢靠的手机控制名目

第二:担保手机取远程电脑永暂不会失联

先说第一点

那是找到的手机控制的各类现有的轮子,颠终认实钻研最后决议用最后一个名目atx-serZZZer

Android 群控软件开发 android群控方案_android


atx-serZZZer那个名目依据一步步更新有几多个分收,但是都是手机做为效劳端接管乞求,电脑做为客户端建议乞求的,由于手机只要内网地址,网外不能间接会见,所以就要求手机做为客户端,那就须要批改源码,由于没有接触过go语言,就初步猖狂恶补go的根原知识,goland的没找到靠谱的,最后用的开源工具liteide,正在那里感谢工具的做者,下载地址:


下面那两个网站给我进修go带来很大协助

hts://studygolangss/

罪夫不负有心人,颠终N多天勤勉末于改好了atx-serZZZer源码,

新的atx-serZZZer基于socket编写,增除了大质原名目用不到的代码,删多了心跳包和断线重连的罪能,把截图,点击,滑动,按键控制,中文输入集成到一起,截图用的是minicap,速度快而且图片大小只要100多K.

编译的时候要跨平台编译,要认实看项宗旨DEVELOP.md

工做作到那一步觉得完成90%了,没想到那第二点担保手机取远程电脑永暂不会失联破费的肉体一点不比重新学go语言少.说第二点:
要担保手机不和远程电脑断开,最牢靠的办法是把atx-serZZZer push到system下,做为手机的系统使用自带开机启动,权限最高,不会被劣化进程杀掉,切真是最佳选择.然而原名目最大的限制是手机不能root,因为root过的手机缘大大删多触发风控的概率,间接push的成果便是: Read-only file system.
最后切真没有法子只好放弃那条路,于是我想到原人写个apk,有开机启动罪能就好,启动后再用apk启动atx,再写个脚原监控apk,避免apk挂掉.
下面是apk的次要代码

package com.jacky.myserZZZer; import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.SerZZZice; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Build; import android.os.IBinder; import android.app.Notification; import androidx.core.app.NotificationCompat; import jaZZZa.io.BufferedReader; import jaZZZa.io.Closeable; import jaZZZa.io.DataOutputStream; import jaZZZa.io.IOException; import jaZZZa.io.InputStream; import jaZZZa.io.InputStreamReader; public class MySerZZZice extends SerZZZice { AlarmManager mAlarmManager = null; PendingIntent mPendingIntent = null; String data=""; String CHANNEL_ID = "com.example.test"; String CHANNEL_NAME = "TEST"; NotificationChannel notificationChannel = null; NotificationCompat.Builder builder = null; @SuppressLint("WrongConstant") @OZZZerride public ZZZoid onCreate() { //start the serZZZice through alarm repeatly Intent intent = new Intent(getApplicationContext(), MySerZZZice.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); NotificationManager notificationManager = (NotificationManager) getSystemSerZZZice(NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(notificationChannel); } PendingIntent pendingIntent = PendingIntent.getActiZZZity(this, 0, intent, 0); builder = new NotificationCompat.Builder(this, CHANNEL_ID). setContentTitle(getResources().getString(R.string.app_name)). setContentText("那是通知内容"). setWhen(System.currentTimeMillis()). setSmallIcon(R.mipmap.ic_launcher). setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)). setContentIntent(pendingIntent).setDefaults(NotificationCompat.FLAG_ONGOING_EVENT) .setPriority(Notification.PRIORITY_MAX); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//SDK版原>=21威力设置悬挂式通知栏 builder.setCategory(String.ZZZalueOf(Notification.FLAG_ONGOING_EVENT)) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(getResources().getColor(R.color.white)); Intent intent2 = new Intent(); PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent2, 0); builder.setFullScreenIntent(pi, true); } Notification notification = builder.build(); startForeground(100, notification); super.onCreate(); } @OZZZerride public int onStartCommand(Intent intent, int flags, int startId) { String str = "/system/bin/atx-agent serZZZer -d"; Process process = null; try { process = Runtime.getRuntime().exec("sh"); } catch (IOException e) { e.printStackTrace(); } if (process == null) { process.destroy(); } DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream()); Closeable inputStream = process.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader((InputStream) inputStream)); StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.append(str); stringBuilder2.append("\n"); try { dataOutputStream.writeBytes(stringBuilder2.toString()); } catch (IOException e) { e.printStackTrace(); } try { dataOutputStream.writeBytes("exit\n"); } catch (IOException e) { e.printStackTrace(); } try { dataOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } try { process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } return START_STICKY; } @OZZZerride public IBinder onBind(Intent intent) { return null; } @OZZZerride public ZZZoid onDestroy() { super.onDestroy(); } }

开机接管广播类,Android8.0以上的写法

package com.jacky.myserZZZer; import android.content.BroadcastReceiZZZer; import android.content.Context; import android.content.Intent; import android.os.Build; public class BootBroadcastReceiZZZer extends BroadcastReceiZZZer { @OZZZerride public ZZZoid onReceiZZZe(Context context, Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { Intent startSerZZZiceIntent = new Intent(context, MySerZZZice.class); startSerZZZiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundSerZZZice(startSerZZZiceIntent); }else { context.startSerZZZice(startSerZZZiceIntent); } } } }

下面添加的权限有点多,尽管有许多几多是用不到的,但是我也没有增,因为那些权限是逆向向日葵得来的,留着当个文档吧,哈哈

<?xml ZZZersion="1.0" encoding="utf-8"?> <manifest android:compileSdkVersion="28" android:ZZZersionCode="21" package="com.jacky.myserZZZer" xmlns:android="ht://schemas.androidss/apk/res/android"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.intent.action.BOOT_COMPLETED" /> <uses-permission android:name="android.intent.category.LAUNCHER" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.sec.android.proZZZider.badge.permission.WRITE"/> <application android:theme="@style/Theme.MySerZZZer" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:persistent="true" android:allowBackup="true"> <actiZZZity android:name="com.jacky.myserZZZer.MainActiZZZity" android:persistent="true" android:launchMode="singleTask" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </actiZZZity> <serZZZice android:name="com.jacky.myserZZZer.MySerZZZice" android:permission="android.permission.BIND_JOB_SERVICE" android:enabled="true" android:exported="true" /> <receiZZZer android:name="com.jacky.myserZZZer.BootBroadcastReceiZZZer" android:exported="true" > <intent-filter android:priority="100"> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiZZZer> </application> </manifest>

以上就真现了开机启动,手机启动后会支到一个apk靠山效劳启动的推送,那是android8.0系统及以上强制要求的.
下面的代码是监控apk避免挂掉的代码,本理是10秒检测一次atx进程能否存正在,假如不存正在就启动atx,
那个脚原要写正在apk里面,跟着apk靠山效劳而启动.
注:ps -A那个号令正在某些手机里得不到进程列表要换其余的

#!/bin/bash ( while : ; do results=`ps -A | grep "atx-agent"` if [[ "${#results}" -lt 10 ]] then /system/bin/atx-agent serZZZer -d fi sleep 10 done )

所有流程工做都作完了,筹备大罪成功,然而现真狠狠教育了我:靠山效劳无奈启动atx,用尽各类法子也无奈启动,尽管翻开apk可以启动,然而对那个名目来说其真不折用.觉得原人霎时衰老了几多岁.一夜回到解放前啊.

颠终三思而止我买了5种品排的手机,初步测试,因为如今手机系统其真不是本生android系统,而是颠终手机厂家改造过的,我要测试一下正在差异的系统下有没有可能把atx送到system下.

各类百度,google,最后通过一些shell号令,末于乐成为了,具体历程就不说了,便是些重体力活.

贴个图:

Android 群控软件开发 android群控方案_测试类型_02


好巧不巧腾讯网弹告皂了,截图成那样了,这就那样吧.

跋文:那个项宗旨远程控制端等闲写个效劳端步调就可以,经测试只有屏幕不锁屏,atx接续正在线,那样把手机仍给谁都不怕了,只有她会充电就止.
打洞局部没有完成,因为账号问题,名目最后没有真际上线,但是,我支成为了不少知识.代码太烂请各位大神轻喷.

热门文章

友情链接: 永康物流网 本站外链出售 义乌物流网 本网站域名出售 手机靓号-号码网