├── SuitScreen
├── adb
│ ├── adb.exe
│ ├── AdbWinApi.dll
│ └── AdbWinUsbApi.dll
├── images
│ ├── tu.png
│ ├── ._back.png
│ ├── ._home.png
│ ├── ._logo.png
│ ├── ._menu.png
│ ├── ._text.jpg
│ ├── ._tu.png
│ ├── back.png
│ ├── home.png
│ ├── logo.png
│ ├── menu.png
│ ├── text.jpg
│ ├── phone_ok.png
│ ├── ._phone_ing.png
│ ├── ._phone_off.png
│ ├── ._phone_ok.png
│ ├── archermind.png
│ ├── phone_ing.png
│ ├── phone_null.png
│ ├── phone_off.png
│ ├── ._archermind.png
│ ├── ._phone_null.png
│ ├── startInstall.png
│ ├── ._bitbug_favicon.ico
│ ├── ._startInstall.png
│ └── bitbug_favicon.ico
├── bin
│ └── com
│ │ └── suitscreen
│ │ └── batchinstall
│ │ ├── Tool.class
│ │ ├── Config.class
│ │ ├── Device.class
│ │ ├── Function.class
│ │ ├── DeviceInfo.class
│ │ ├── ui
│ │ └── MainBash.class
│ │ ├── ApkInstallInfo.class
│ │ ├── DeviceBuffer.class
│ │ ├── ApkInstallBuffer.class
│ │ └── process
│ │ ├── FoucsHandle.class
│ │ ├── InstallAppThread.class
│ │ └── RemoveAppThread.class
└── src
│ └── com
│ └── suitscreen
│ └── batchinstall
│ ├── Device.java
│ ├── Config.java
│ ├── ApkInstallInfo.java
│ ├── ApkInstallBuffer.java
│ ├── Tool.java
│ ├── DeviceBuffer.java
│ ├── Function.java
│ ├── DeviceInfo.java
│ ├── process
│ ├── FoucsHandle.java
│ ├── RemoveAppThread.java
│ └── InstallAppThread.java
│ └── ui
│ └── MainBash.java
├── SuitScreenMobile
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── values-sw600dp
│ │ └── dimens.xml
│ ├── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── menu
│ │ └── main.xml
│ ├── values-sw720dp-land
│ │ └── dimens.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── layout
│ │ └── activity_main.xml
├── project.properties
├── proguard-project.txt
├── src
│ └── com
│ │ └── suitscreen
│ │ └── app
│ │ ├── mobiles
│ │ ├── ServiceBroadcastReceiver.java
│ │ ├── Tool.java
│ │ └── SocketService.java
│ │ └── providers
│ │ ├── SuitScreen.java
│ │ ├── SuitDatabaseHelper.java
│ │ ├── SQLiteContentProvider.java
│ │ └── SuitProvider.java
└── AndroidManifest.xml
└── README.md
/SuitScreen/adb/adb.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/adb/adb.exe
--------------------------------------------------------------------------------
/SuitScreen/images/tu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/tu.png
--------------------------------------------------------------------------------
/SuitScreen/adb/AdbWinApi.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/adb/AdbWinApi.dll
--------------------------------------------------------------------------------
/SuitScreen/images/._back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._back.png
--------------------------------------------------------------------------------
/SuitScreen/images/._home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._home.png
--------------------------------------------------------------------------------
/SuitScreen/images/._logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._logo.png
--------------------------------------------------------------------------------
/SuitScreen/images/._menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._menu.png
--------------------------------------------------------------------------------
/SuitScreen/images/._text.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._text.jpg
--------------------------------------------------------------------------------
/SuitScreen/images/._tu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._tu.png
--------------------------------------------------------------------------------
/SuitScreen/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/back.png
--------------------------------------------------------------------------------
/SuitScreen/images/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/home.png
--------------------------------------------------------------------------------
/SuitScreen/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/logo.png
--------------------------------------------------------------------------------
/SuitScreen/images/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/menu.png
--------------------------------------------------------------------------------
/SuitScreen/images/text.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/text.jpg
--------------------------------------------------------------------------------
/SuitScreen/images/phone_ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/phone_ok.png
--------------------------------------------------------------------------------
/SuitScreen/adb/AdbWinUsbApi.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/adb/AdbWinUsbApi.dll
--------------------------------------------------------------------------------
/SuitScreen/images/._phone_ing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._phone_ing.png
--------------------------------------------------------------------------------
/SuitScreen/images/._phone_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._phone_off.png
--------------------------------------------------------------------------------
/SuitScreen/images/._phone_ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._phone_ok.png
--------------------------------------------------------------------------------
/SuitScreen/images/archermind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/archermind.png
--------------------------------------------------------------------------------
/SuitScreen/images/phone_ing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/phone_ing.png
--------------------------------------------------------------------------------
/SuitScreen/images/phone_null.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/phone_null.png
--------------------------------------------------------------------------------
/SuitScreen/images/phone_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/phone_off.png
--------------------------------------------------------------------------------
/SuitScreen/images/._archermind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._archermind.png
--------------------------------------------------------------------------------
/SuitScreen/images/._phone_null.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._phone_null.png
--------------------------------------------------------------------------------
/SuitScreen/images/startInstall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/startInstall.png
--------------------------------------------------------------------------------
/SuitScreen/images/._bitbug_favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._bitbug_favicon.ico
--------------------------------------------------------------------------------
/SuitScreen/images/._startInstall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/._startInstall.png
--------------------------------------------------------------------------------
/SuitScreen/images/bitbug_favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/images/bitbug_favicon.ico
--------------------------------------------------------------------------------
/SuitScreenMobile/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreenMobile/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SuitScreenMobile/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreenMobile/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/Tool.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/Tool.class
--------------------------------------------------------------------------------
/SuitScreenMobile/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreenMobile/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SuitScreenMobile/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreenMobile/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/Config.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/Config.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/Device.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/Device.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/Function.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/Function.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/DeviceInfo.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/DeviceInfo.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/ui/MainBash.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/ui/MainBash.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/ApkInstallInfo.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/ApkInstallInfo.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/DeviceBuffer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/DeviceBuffer.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/ApkInstallBuffer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/ApkInstallBuffer.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/process/FoucsHandle.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/process/FoucsHandle.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/process/InstallAppThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/process/InstallAppThread.class
--------------------------------------------------------------------------------
/SuitScreen/bin/com/suitscreen/batchinstall/process/RemoveAppThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haicom/SuitScreenTool/HEAD/SuitScreen/bin/com/suitscreen/batchinstall/process/RemoveAppThread.class
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SuitScreenTool
2 | ==============
3 |
4 | 自动化测试工具,可以通过真机测试安装包的可用性。
5 | 这个工具分为PC端和Android 端。
6 | PC端主要是负责并发的安装和卸载(针对多台手机),手机端主要是负责验证包的可用性并且记录。
7 | 涉及到的技术有adb socket通信,并发机制,后台服务的启动,等等技术。对性能的要求是越快越好。
8 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SuitScreen_Android
5 | Settings
6 | Hello world!
7 |
8 | 数据库保存发生错误!
9 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/Device.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | public class Device {
4 |
5 | public Device(String serialNo, int status) {
6 |
7 | this.serialNo = serialNo;
8 | this.status = status;
9 | }
10 |
11 | public String serialNo; // 终端串号
12 | public int status; // 状态
13 | }
14 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/Config.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | public class Config {
4 |
5 | public static final String FONT_NAME = "文泉驿等宽正黑";
6 |
7 | /** <----公共变量----> */
8 | public static boolean isStartInstall = false; // 是否开始安装
9 | /** ----公共变量----> */
10 | public static String getPicturePath() {
11 | return mPicturePath;
12 | }
13 |
14 | public static void setPicturePath(String picturePath) {
15 | mPicturePath = picturePath;
16 | }
17 |
18 | private static String mPicturePath;
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/SuitScreenMobile/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/SuitScreenMobile/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/SuitScreenMobile/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
16 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/mobiles/ServiceBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.mobiles;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.util.Log;
7 |
8 | public class ServiceBroadcastReceiver extends BroadcastReceiver {
9 | private static final String TAG = "SocketService";
10 | private static String START_ACTION = "NotifyServiceStart";
11 | private static String STOP_ACTION = "NotifyServiceStop";
12 |
13 | @Override
14 | public void onReceive(Context context, Intent intent) {
15 | String action = intent.getAction();
16 | Log.d(TAG, "MyReceiver onReceive action = " + action);
17 |
18 | if ( START_ACTION.equalsIgnoreCase(action) ) {
19 |
20 | context.startService(new Intent(context, SocketService.class));
21 |
22 | } else if ( STOP_ACTION.equalsIgnoreCase(action) ) {
23 |
24 | context.stopService(new Intent(context, SocketService.class));
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/ApkInstallInfo.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | public class ApkInstallInfo {
4 | public static final int INSTALL_PREPARE = -1; //设备为安装准备状态
5 | public static final int INSTALL_PROGRESS = 0; //设备为安装进行中
6 | public static final int INSTALL_FINISH = 1; //设备为安装完成时
7 | public static final int INSTALL_ERROR = 2; //设备为安装结束
8 | public static final int REMOVE_FINISH = 3; //设备删除完成
9 |
10 | public ApkInstallInfo() {
11 | mInstallStatus = INSTALL_PREPARE;
12 | }
13 |
14 | public String getApkName() {
15 | return mApkName;
16 | }
17 | public void setApkName(String apkName) {
18 | this.mApkName = apkName;
19 | }
20 | public String getApkPath() {
21 | return mApkPath;
22 | }
23 | public void setApkPath(String apkPath) {
24 | this.mApkPath = apkPath;
25 | }
26 | public synchronized int getInstallStatus() {
27 | return mInstallStatus;
28 | }
29 | public synchronized void setInstallStatus(int installStatus) {
30 | this.mInstallStatus = installStatus;
31 | }
32 | private String mApkName; //apk姓名
33 | private String mApkPath; //apk安装路径
34 | private volatile int mInstallStatus; //apk安装结果
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/ApkInstallBuffer.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 |
4 | import java.util.ArrayList;
5 |
6 | public class ApkInstallBuffer {
7 |
8 | public static ApkInstallBuffer getInstance() {
9 |
10 | if (mInstance == null) {
11 | mInstance = new ApkInstallBuffer();
12 | }
13 |
14 | return mInstance;
15 | }
16 |
17 | private ApkInstallBuffer() {
18 | mList = new ArrayList( );
19 | }
20 |
21 | public synchronized boolean add(ApkInstallInfo installInfo) {
22 |
23 | for (int index = 0; index < mList.size(); index++) {
24 | ApkInstallInfo info = mList.get(index);
25 | if ( info.getApkName().equals( installInfo.getApkName() ) ) {
26 | return false;
27 | }
28 | }
29 |
30 | System.out.println(" ApkInstallBuffer installInfo = " + installInfo.getApkName() );
31 | mList.add(installInfo);
32 | return true;
33 | }
34 |
35 |
36 | public synchronized ApkInstallInfo get(int index) {
37 | return mList.get(index);
38 | }
39 |
40 | public synchronized void remove(ApkInstallInfo installInfo) {
41 | mList.remove(installInfo);
42 | }
43 |
44 | public synchronized void remove(int index) {
45 | mList.remove(index);
46 | }
47 |
48 | public synchronized void clear() {
49 | mList.clear();
50 | }
51 |
52 | public synchronized int size() {
53 | return mList.size();
54 | }
55 |
56 | private static ApkInstallBuffer mInstance;
57 | private ArrayList mList;
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/providers/SuitScreen.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.providers;
2 |
3 | import android.net.Uri;
4 | import android.provider.BaseColumns;
5 |
6 |
7 | public class SuitScreen {
8 | private final static String TAG = "SuitScreen";
9 | /** The authority for the contacts provider */
10 | public static final String AUTHORITY = "suitscreenapp";
11 | /** A content:// style uri to the authority for the contacts provider */
12 | public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
13 |
14 | // Constructor
15 | public SuitScreen() {
16 |
17 | }
18 |
19 | public static final class InstalledApp implements BaseColumns {
20 | /**
21 | * The content:// style URL for this table
22 | */
23 | public static final Uri CONTENT_URI =
24 | Uri.withAppendedPath(AUTHORITY_URI, "install");
25 |
26 |
27 | public static final String PACKAGE_NAME = "package_name";
28 | public static final String CLASS_NAME = "class_name";
29 | public static final String ACTIVITY_START = "activity_start";
30 |
31 | /**
32 | * The "deleted" flag: "0" by default, "1" if the row has been marked
33 | * for deletion.
34 | * Type: INTEGER
35 | */
36 | public static final String APP_DELETED = "deleted";
37 |
38 | public static final String DATE = "date";
39 |
40 |
41 | /**
42 | * The MIME type of {@link #CONTENT_URI} providing a directory of
43 | * people.
44 | */
45 | public static final String CONTENT_TYPE = "vnd.android.cursor.dir/install";
46 |
47 | /**
48 | * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
49 | * person.
50 | */
51 | public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/install";
52 |
53 | /**
54 | * The default sort order for this table
55 | */
56 | public static final String DEFAULT_SORT_ORDER = "date ASC ";
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/SuitScreenMobile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
27 |
28 |
29 |
30 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/providers/SuitDatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.providers;
2 |
3 | import com.suitscreen.app.providers.SuitScreen.InstalledApp;
4 |
5 | import android.content.Context;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.database.sqlite.SQLiteOpenHelper;
8 | import android.util.Log;
9 |
10 | public class SuitDatabaseHelper extends SQLiteOpenHelper {
11 | private final static String TAG = "BreezingDatabaseHelper";
12 | private static SuitDatabaseHelper sInstance = null;
13 | static final String DATABASE_NAME = "suitscreen.db";
14 | static final int DATABASE_VERSION = 1;
15 | private final Context mContext;
16 |
17 |
18 |
19 | private SuitDatabaseHelper(Context context) {
20 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
21 | mContext = context;
22 | }
23 |
24 | /**
25 | * Return a singleton helper for the combined Breezing health
26 | * database.
27 | */
28 | /* package */
29 | static synchronized SuitDatabaseHelper getInstance(Context context) {
30 | if (sInstance == null) {
31 | sInstance = new SuitDatabaseHelper(context);
32 | }
33 | return sInstance;
34 | }
35 |
36 | @Override
37 | public void onCreate(SQLiteDatabase db) {
38 | createInstallAppTables(db);
39 | }
40 |
41 |
42 | private void createInstallAppTables(SQLiteDatabase db) {
43 | db.execSQL("CREATE TABLE " + SuitProvider.TABLE_INSTALL_APP + " ("
44 | + InstalledApp._ID + " INTEGER PRIMARY KEY, "
45 | + InstalledApp.PACKAGE_NAME + " TEXT NOT NULL , "
46 | + InstalledApp.CLASS_NAME + " TEXT NOT NULL , "
47 | + InstalledApp.ACTIVITY_START + " BOOL NOT NULL DEFAULT 0 ,"
48 | + InstalledApp.APP_DELETED + " BOOL NOT NULL DEFAULT 0 ,"
49 | + InstalledApp.DATE + " TEXT NOT NULL " +
50 | ");");
51 | }
52 |
53 |
54 |
55 | @Override
56 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
57 | Log.d(TAG, " onUpgrade oldVersion = " + oldVersion + " newVersion = " + newVersion);
58 | }
59 |
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/Tool.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 |
4 |
5 |
6 |
7 | public class Tool {
8 | //int、char、double与byte相互转换的程序
9 | //整数到字节数组的转换
10 |
11 | public static byte[] intToByte(int number) {
12 | int temp = number;
13 | byte[] b = new byte[4];
14 |
15 | for ( int i=b.length-1; i>-1; i-- ) {
16 | b[i] = new Integer(temp&0xff).byteValue();//将最高位保存在最低位
17 | temp = temp >> 8;//向右移8位
18 | }
19 |
20 | return b;
21 | }
22 |
23 |
24 | //字节数组到整数的转换
25 | public static int byteToInt(byte[] b) {
26 | int s = 0;
27 | for (int i = 0; i < 3; i++) {
28 | if ( b[i] >= 0 )
29 | s = s + b[i];
30 | else
31 | s = s + 256 + b[i];
32 |
33 | s = s * 256;
34 | }
35 |
36 | if (b[3] >= 0) //最后一个之所以不乘,是因为可能会溢出
37 | s = s + b[3];
38 | else
39 | s = s + 256 + b[3];
40 |
41 | return s;
42 | }
43 |
44 | //字符到字节转换
45 |
46 | public static byte[] charToByte(char ch) {
47 | int temp=(int)ch;
48 | byte[] b=new byte[2];
49 | for (int i=b.length-1;i>-1;i--) {
50 | b[i] = new Integer(temp&0xff).byteValue();//将最高位保存在最低位
51 | temp = temp >> 8;//向右移8位
52 | }
53 | return b;
54 |
55 | }
56 |
57 | //字节到字符转换
58 | public static char byteToChar(byte[] b){
59 | int s=0;
60 | if ( b[0] > 0 )
61 | s+=b[0];
62 | else
63 | s+=256+b[0];
64 |
65 | s*=256;
66 |
67 | if(b[1]>0)
68 | s+=b[1];
69 | else
70 | s+=256+b[1];
71 |
72 | char ch=(char)s;
73 |
74 | return ch;
75 | }
76 |
77 | //浮点到字节转换
78 |
79 | public static byte[] doubleToByte(double d) {
80 | byte[] b=new byte[8];
81 | long l=Double.doubleToLongBits(d);
82 |
83 | for ( int i=0; i>8;
86 | }
87 | return b;
88 | }
89 |
90 | //字节到浮点转换
91 |
92 | public static double byteToDouble(byte[] b) {
93 | long l;
94 | l=b[0];
95 | l&=0xff;
96 | l|=((long)b[1]<<8);
97 | l&=0xffff;
98 | l|=((long)b[2]<<16);
99 | l&=0xffffff;
100 | l|=((long)b[3]<<24);
101 | l&=0xffffffffl;
102 | l|=((long)b[4]<<32);
103 | l&=0xffffffffffl;
104 | l|=((long)b[5]<<40);
105 | l&=0xffffffffffffl;
106 | l|=((long)b[6]<<48);
107 | l&=0xffffffffffffffl;
108 | l|=((long)b[7]<<56);
109 | return Double.longBitsToDouble(l);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/mobiles/Tool.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.mobiles;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 |
6 |
7 | public class Tool {
8 | //int、char、double与byte相互转换的程序
9 | //整数到字节数组的转换
10 | @SuppressLint("UseValueOf")
11 | public static byte[] intToByte(int number) {
12 | int temp = number;
13 | byte[] b = new byte[4];
14 |
15 | for ( int i=b.length-1; i>-1; i-- ) {
16 | b[i] = new Integer(temp&0xff).byteValue();//将最高位保存在最低位
17 | temp = temp >> 8;//向右移8位
18 | }
19 |
20 | return b;
21 | }
22 |
23 |
24 | //字节数组到整数的转换
25 | public static int byteToInt(byte[] b) {
26 | int s = 0;
27 | for (int i = 0; i < 3; i++) {
28 | if ( b[i] >= 0 )
29 | s = s + b[i];
30 | else
31 | s = s + 256 + b[i];
32 |
33 | s = s * 256;
34 | }
35 |
36 | if (b[3] >= 0) //最后一个之所以不乘,是因为可能会溢出
37 | s = s + b[3];
38 | else
39 | s = s + 256 + b[3];
40 |
41 | return s;
42 | }
43 |
44 | //字符到字节转换
45 | @SuppressLint("UseValueOf")
46 | public static byte[] charToByte(char ch) {
47 | int temp=(int)ch;
48 | byte[] b=new byte[2];
49 | for (int i=b.length-1;i>-1;i--) {
50 | b[i] = new Integer(temp&0xff).byteValue();//将最高位保存在最低位
51 | temp = temp >> 8;//向右移8位
52 | }
53 | return b;
54 |
55 | }
56 |
57 | //字节到字符转换
58 | public static char byteToChar(byte[] b){
59 | int s=0;
60 | if ( b[0] > 0 )
61 | s+=b[0];
62 | else
63 | s+=256+b[0];
64 |
65 | s*=256;
66 |
67 | if(b[1]>0)
68 | s+=b[1];
69 | else
70 | s+=256+b[1];
71 |
72 | char ch=(char)s;
73 |
74 | return ch;
75 | }
76 |
77 | //浮点到字节转换
78 | @SuppressLint("UseValueOf")
79 | public static byte[] doubleToByte(double d) {
80 | byte[] b=new byte[8];
81 | long l=Double.doubleToLongBits(d);
82 |
83 | for ( int i=0; i>8;
86 | }
87 | return b;
88 | }
89 |
90 | //字节到浮点转换
91 |
92 | public static double byteToDouble(byte[] b) {
93 | long l;
94 | l=b[0];
95 | l&=0xff;
96 | l|=((long)b[1]<<8);
97 | l&=0xffff;
98 | l|=((long)b[2]<<16);
99 | l&=0xffffff;
100 | l|=((long)b[3]<<24);
101 | l&=0xffffffffl;
102 | l|=((long)b[4]<<32);
103 | l&=0xffffffffffl;
104 | l|=((long)b[5]<<40);
105 | l&=0xffffffffffffl;
106 | l|=((long)b[6]<<48);
107 | l&=0xffffffffffffffl;
108 | l|=((long)b[7]<<56);
109 | return Double.longBitsToDouble(l);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/DeviceBuffer.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Vector;
5 |
6 | public class DeviceBuffer {
7 |
8 | private static volatile int port = 10001;
9 |
10 | public static DeviceBuffer getInstance() {
11 |
12 | if (instance == null) {
13 | instance = new DeviceBuffer();
14 | }
15 |
16 | return instance;
17 | }
18 |
19 | private DeviceBuffer() {
20 | list = new Vector( );
21 | }
22 |
23 | public synchronized boolean add(DeviceInfo devInfo) {
24 |
25 | for (int i = 0; i < list.size(); i++) {
26 | DeviceInfo info = list.get(i);
27 | if ( info.getDevSerial().equals(devInfo.getDevSerial() ) ) {
28 | return false;
29 | }
30 | }
31 |
32 | list.add(devInfo);
33 | return true;
34 | }
35 |
36 | public synchronized void refresh(ArrayList devList) {
37 |
38 | DeviceInfo info = null;
39 | // 正向轮询加入新的设备
40 | for (int i = 0; i < devList.size(); i++) {
41 | Device dev = devList.get(i);
42 | boolean isExist = false;
43 | for (int j = 0; j < list.size(); j++) {
44 |
45 | info = list.get(j);
46 | if ( info.getDevSerial().equals(dev.serialNo)) {
47 | isExist = true;
48 | if (dev.status == DeviceInfo.STATUS_OFFLINE) {
49 | info.setStatus(DeviceInfo.STATUS_OFFLINE);
50 | }
51 |
52 | if ( dev.status == DeviceInfo.STATUS_PLUGIN
53 | && info.getStatus() == DeviceInfo.STATUS_OFFLINE) {
54 | info.setStatus(dev.status);
55 | }
56 | break;
57 | }
58 | }
59 |
60 | if (!isExist) {
61 | if (port++ > 19999) {
62 | port = 10001;
63 | }
64 | list.add( new DeviceInfo(dev.serialNo, dev.status, port) );
65 | }
66 | }
67 |
68 | // 反向轮询删除被拔出的设备
69 | for (int i = 0; i < list.size(); i++) {
70 |
71 | boolean isPulled = true; // 默认已被拔出
72 | info = list.get(i);
73 | for (int j = 0; j < devList.size(); j++) {
74 |
75 | if (info.getDevSerial().equals(devList.get(j).serialNo)) {
76 | isPulled = false;
77 | continue;
78 | }
79 | }
80 |
81 | if (isPulled) {
82 | info.setStatus(DeviceInfo.STATUS_PULLED); // 标识设备已经拔出
83 | }
84 | }
85 | }
86 |
87 | public synchronized DeviceInfo get(int index) {
88 | return list.get(index);
89 | }
90 |
91 | public synchronized void remove(DeviceInfo devInfo) {
92 | list.remove(devInfo);
93 | }
94 |
95 | public synchronized void remove(int index) {
96 | list.remove(index);
97 | }
98 |
99 | public synchronized void clear() {
100 | list.clear();
101 | }
102 |
103 | public synchronized int size() {
104 | return list.size();
105 | }
106 |
107 | static private DeviceBuffer instance;
108 | private Vector list;
109 | }
110 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/Function.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 |
8 | import com.suitscreen.batchinstall.ui.MainBash;
9 |
10 |
11 | public class Function {
12 |
13 | /**
14 | * open Screenshot Dir
15 | *
16 | * @param folder
17 | */
18 | public static void open_directory(String folder) {
19 |
20 | File file = new File(folder);
21 | if (!file.exists()) {
22 | return;
23 | }
24 |
25 | Runtime runtime = null;
26 |
27 | try {
28 | String SysType = System.getProperties().getProperty("os.name");
29 | if (SysType.startsWith("win") || SysType.startsWith("Win")) {
30 | String[] cmd = new String[5];
31 | cmd[0] = "cmd";
32 | cmd[1] = "/c";
33 | cmd[2] = "start";
34 | cmd[3] = " ";
35 | cmd[4] = folder;
36 | Runtime.getRuntime().exec(cmd);
37 | } else {
38 | runtime = Runtime.getRuntime();
39 | runtime.exec("nautilus " + folder);
40 | }
41 |
42 | } catch (IOException ex) {
43 | ex.printStackTrace();
44 | } finally {
45 | if (null != runtime) {
46 | runtime.runFinalization();
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * 执行dos命令,返回命令输出的字符串
53 | *
54 | * @param cmd
55 | * , 要执行的命令
56 | * @return 命令执行的返回字符串
57 | */
58 | public static String exec(String cmd) {
59 | StringBuffer sb = new StringBuffer();
60 | Process process = null;
61 | InputStreamReader in = null;
62 | BufferedReader reader = null;
63 | try {
64 | process = Runtime.getRuntime().exec(cmd); // 启动另一个进程来执行命令
65 | in = new InputStreamReader(process.getInputStream());
66 | reader = new BufferedReader(in);
67 |
68 | String line = null;
69 | while ( ( line = reader.readLine() ) != null) {
70 | sb.append(line).append("\r\n");
71 | }
72 | } catch (Exception e) {
73 | e.printStackTrace();
74 | } finally {
75 | if (process != null) {
76 | try {
77 | reader.close();
78 | in.close();
79 | } catch (IOException e) {
80 | e.printStackTrace();
81 | }
82 |
83 | process.destroy();
84 | }
85 | }
86 | return sb.toString();
87 | }
88 |
89 | /**
90 | * 屏幕截图
91 | *
92 | * @param devInfo
93 | */
94 | public static String screenCap(DeviceInfo devInfo) {
95 |
96 | String fileDir = Config.getPicturePath() + File.separator + devInfo.getDevModel();
97 | long time = System.currentTimeMillis();
98 | // 开始截图
99 | String cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial()
100 | + " shell /system/bin/screencap -p " + "/sdcard/" + time
101 | + ".png";
102 | String result = exec(cmd);
103 |
104 | if ( result.length() == 0 ) {
105 | cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial()
106 | + " shell /system/bin/screencapture -p " + "/sdcard/" + time
107 | + ".png";
108 | exec(cmd);
109 | }
110 |
111 |
112 |
113 | System.out.println("screenCap result = " + result);
114 | // 传送到pc端
115 | cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial() + " pull /sdcard/" + time + ".png "
116 | + fileDir;
117 | exec(cmd);
118 |
119 | // 删除手机上的截图文件
120 | cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial() + " shell rm -r /sdcard/" + time
121 | + ".png";
122 | exec(cmd);
123 |
124 | String imageName = fileDir + File.separator + time + ".png ";
125 | return imageName;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/DeviceInfo.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall;
2 |
3 | import java.util.concurrent.ArrayBlockingQueue;
4 |
5 | /**
6 | * 定义设备信息类 定义设备的一些基本属性
7 | *
8 | * @author gaoxusong
9 | * @serial
10 | */
11 | public class DeviceInfo {
12 |
13 | public static final int STATUS_OFFLINE = -1; // 设备为离线状态
14 | public static final int STATUS_PLUGIN = 0; // 设备插入
15 | public static final int STATUS_START_INSTALL = 1; // 开始安装
16 | public static final int STATUS_END_INSTALL = 2; // 安装结束
17 | public static final int STATUS_START_REMOVE = 4;//设备卸载完成
18 | public static final int STATUS_REMOVE_FINISH = 5;//设备卸载完成
19 | public static final int STATUS_PULLED = 6; // 设备拔出
20 |
21 | private static final String INIT_PORT_STATUS = "即将安装...";
22 | private static final String INIT_DEVICE_MODEL = "正在获取...";
23 |
24 |
25 | public static final String INSTALL_PROGRAM_STATUS = "正在安装守护程序";
26 | public static final String LUNCHER_PROGRAM_STATUS = "正在启动守护程序";
27 | public static final String START_INSTALL_PROGRAM_STATUS = "开始安装应用";
28 | public static final String INSTALL_PROGRAM_ERRO = "安装应用失败,请重新连接手机";
29 | public static final String INSTALL_PROGRAM_BREAK_DOWN = "安装过程中出现故障,请检查并重新插拔手机。";
30 | public static final String FORWARD_PORT_MAP = "正在映射转发端口";
31 |
32 |
33 | public static final int CMD_GET_MODEL = 0x01;
34 | public static final int CMD_CHECK_ACTIVITY_START = 0x04;
35 | public static final int CMD_GET_PACKAGENAME = 0x05;
36 | public static final int CMD_GET_ALL_PACKAGENAME = 0x06;
37 | public static final int CMD_EXIT = 0x09;
38 |
39 | public int MAX_INSTALL_NUMBER = 10;
40 |
41 | public DeviceInfo(String serial, int stat, int port) {
42 | this.mDevModel = INIT_DEVICE_MODEL;
43 | this.mDevSerial = serial;
44 | this.mMapPort = port;
45 | this.mStatus = stat;
46 | this.mStatusString = INIT_PORT_STATUS;
47 | this.mQueue = new ArrayBlockingQueue(MAX_INSTALL_NUMBER);
48 | }
49 |
50 |
51 |
52 | public DeviceInfo(String serial, int port) {
53 | this.mDevModel = INIT_DEVICE_MODEL;
54 | this.mDevSerial = serial;
55 | this.mMapPort = port;
56 | this.mStatus = 0;
57 | this.mStatusString = INIT_PORT_STATUS;
58 | }
59 |
60 |
61 | public String getApkPath() {
62 | return mApkPath;
63 | }
64 |
65 | public void setApkPath(String apkPath) {
66 | this.mApkPath = apkPath;
67 | }
68 |
69 | public synchronized int getStatus() {
70 | return mStatus;
71 | }
72 |
73 | public synchronized void setStatus(int status) {
74 | this.mStatus = status;
75 | }
76 |
77 | public String getDevModel() {
78 | return mDevModel;
79 | }
80 |
81 |
82 |
83 | public void setDevModel(String devModel) {
84 | this.mDevModel = devModel;
85 | }
86 |
87 | public String getDevSerial() {
88 | return mDevSerial;
89 | }
90 |
91 | public void setDevSerial(String devSerial) {
92 | this.mDevSerial = devSerial;
93 | }
94 |
95 | public int getMapPort() {
96 | return mMapPort;
97 | }
98 |
99 | public void setmMapPort(int mapPort) {
100 | this.mMapPort = mapPort;
101 | }
102 |
103 | public String getStatusString() {
104 | return mStatusString;
105 | }
106 |
107 | public void setStatusString(String statusString) {
108 | this.mStatusString = statusString;
109 | }
110 |
111 | public synchronized ArrayBlockingQueue getQueue() {
112 | return mQueue;
113 | }
114 |
115 | public synchronized void setQueue(ArrayBlockingQueue queue) {
116 | this.mQueue = queue;
117 | }
118 |
119 | private int mMapPort; // adb映射到设备的socket端口
120 | private String mStatusString; // 状态描述字符串
121 | private String mDevSerial; // 设备序列号
122 | private String mDevModel; // 设备型号
123 | private String mApkPath; //apk安装路径
124 | private volatile int mStatus; // 设备在操作过程中的状态:-1-掉线;0-插入;1-开始安装;2-安装完毕;3-设备被拔出
125 | private ArrayBlockingQueue mQueue;
126 | }
127 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/process/FoucsHandle.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall.process;
2 |
3 | import java.util.concurrent.ExecutorService;
4 | import java.util.concurrent.Executors;
5 | import com.suitscreen.batchinstall.ApkInstallBuffer;
6 | import com.suitscreen.batchinstall.ApkInstallInfo;
7 | import com.suitscreen.batchinstall.DeviceBuffer;
8 | import com.suitscreen.batchinstall.DeviceInfo;
9 |
10 |
11 |
12 | public class FoucsHandle {
13 | // private ExecutorService pool;
14 |
15 |
16 | private static DeviceBuffer mDevBuffer;
17 | private static ApkInstallBuffer mInstallBuffer;
18 | private static FoucsHandle mInstance;
19 |
20 | private ExecutorService mExec;
21 | private DeviceInfo mDeviceInfo;
22 | // private boolean mDone;
23 |
24 | public static FoucsHandle getInstance() {
25 |
26 | if (mInstance == null) {
27 | mInstance = new FoucsHandle();
28 | }
29 |
30 | return mInstance;
31 | }
32 |
33 | public FoucsHandle( ) {
34 | mDevBuffer = DeviceBuffer.getInstance();
35 | mInstallBuffer = ApkInstallBuffer.getInstance();
36 | mExec = Executors.newCachedThreadPool();
37 | // pool = Executors.newCachedThreadPool();
38 | // mDone = false;
39 | }
40 |
41 |
42 | public void handleInfo() {
43 | boolean installDevice = findInstalledDevice();
44 |
45 | while ( installDevice ) {
46 | System.out.println(" UpdateDeviceThread pool.execute before " );
47 | InstallAppThread installApp = new InstallAppThread(mDeviceInfo);
48 | mExec.execute(installApp);
49 | System.out.println(" UpdateDeviceThread pool.execute after " );
50 | installDevice = findInstalledDevice();
51 | }
52 |
53 | if ( installDevice == false ) {
54 | boolean removeDevice = findRemoveDevice() ;
55 | if ( true == removeDevice ) {
56 | RemoveAppThread removeApp = new RemoveAppThread(mDeviceInfo);
57 | mExec.execute(removeApp);
58 | }
59 | }
60 | }
61 |
62 |
63 |
64 | private synchronized boolean findInstalledDevice() {
65 |
66 | boolean deviceStatus = false;
67 |
68 | ApkInstallInfo apkInstallInfo;
69 |
70 | for (int index = 0; index < mDevBuffer.size(); index++) {
71 |
72 | mDeviceInfo = mDevBuffer.get(index);
73 | System.out.println(" findInstalledDevice index = " + index + " mDeviceInfo.getStatus() = " + mDeviceInfo.getStatus()
74 | + " mDeviceInfo.getApkPath() = " + mDeviceInfo.getApkPath() );
75 |
76 | if ( ( (mDeviceInfo.getStatus() == DeviceInfo.STATUS_PLUGIN)
77 | || (mDeviceInfo.getStatus() == DeviceInfo.STATUS_END_INSTALL)
78 | || (mDeviceInfo.getStatus() == DeviceInfo.STATUS_REMOVE_FINISH) )
79 | && mDeviceInfo.getQueue().size() <= mDeviceInfo.MAX_INSTALL_NUMBER ) {
80 |
81 | for ( int installIndex = 0; installIndex < mInstallBuffer.size(); installIndex++ ) {
82 |
83 | apkInstallInfo = mInstallBuffer.get(installIndex);
84 | System.out.println(" findInstalledDevice installIndex = " + installIndex +
85 | " apkInstallInfo.getInstallStatus() = " + apkInstallInfo.getInstallStatus() );
86 |
87 | if ( ( apkInstallInfo.getInstallStatus() == ApkInstallInfo.INSTALL_PREPARE )
88 | || ( apkInstallInfo.getInstallStatus() == ApkInstallInfo.INSTALL_ERROR ) ) {
89 |
90 | if (apkInstallInfo.getInstallStatus() == ApkInstallInfo.INSTALL_ERROR) {
91 | String apkPath = mDeviceInfo.getApkPath();
92 | System.out.println(" findInstalledDevice apkPath = " + apkPath + " apkInstallInfo.getApkPath() = " + apkInstallInfo.getApkPath());
93 | if ( (apkPath != null)
94 | && (apkPath.length() > 0 ) ) {
95 | if ( apkPath.equals( apkInstallInfo.getApkPath() ) ) {
96 | continue;
97 | }
98 | }
99 | }
100 |
101 | mDeviceInfo.setApkPath( apkInstallInfo.getApkPath() );
102 | mDeviceInfo.setStatus(DeviceInfo.STATUS_START_INSTALL);
103 | apkInstallInfo.setInstallStatus(ApkInstallInfo.INSTALL_PROGRESS);
104 | System.out.println(" findInstalledDevice ApkInstallInfo.INSTALL_PREPARE deviceInfo.devSerial = " + mDeviceInfo.getDevSerial()
105 | + " deviceInfo.status = " + mDeviceInfo.getStatus()
106 | + " mDeviceInfo.getApkPath() = " + mDeviceInfo.getApkPath()
107 | + " installIndex = " + installIndex + " mInstallBuffer.size() = " + mInstallBuffer.size() );
108 | deviceStatus = true;
109 | return deviceStatus;
110 | }
111 | }
112 | }
113 | }
114 |
115 | System.out.println(" UpdateDeviceThread deviceStatus = " + deviceStatus);
116 | return deviceStatus;
117 | }
118 |
119 | private synchronized boolean findRemoveDevice() {
120 | boolean deviceStatus = false;
121 | for (int index = 0; index < mDevBuffer.size(); index++) {
122 |
123 | mDeviceInfo = mDevBuffer.get(index);
124 | System.out.println(" findRemoveDevice index = " + index + " mDeviceInfo.getStatus() = " + mDeviceInfo.getStatus()
125 | + " mDeviceInfo.getApkPath() = " + mDeviceInfo.getApkPath() );
126 |
127 | if ( mDeviceInfo.getStatus() == DeviceInfo.STATUS_END_INSTALL ) {
128 | deviceStatus = true;
129 | mDeviceInfo.setStatus(DeviceInfo.STATUS_START_REMOVE);
130 | return deviceStatus;
131 | }
132 | }
133 |
134 | System.out.println(" UpdateDeviceThread deviceStatus = " + deviceStatus);
135 | return deviceStatus;
136 | }
137 |
138 | // public synchronized void stop() {
139 | // mDone = true;
140 | // }
141 | //
142 |
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/process/RemoveAppThread.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall.process;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.UnsupportedEncodingException;
10 | import java.net.InetAddress;
11 | import java.net.Socket;
12 | import java.net.UnknownHostException;
13 | import java.nio.ByteBuffer;
14 |
15 | import com.suitscreen.batchinstall.ApkInstallBuffer;
16 | import com.suitscreen.batchinstall.DeviceInfo;
17 | import com.suitscreen.batchinstall.Function;
18 | import com.suitscreen.batchinstall.Tool;
19 | import com.suitscreen.batchinstall.ui.MainBash;
20 |
21 | public class RemoveAppThread implements Runnable {
22 | private Socket mSocket; // Socket客户端
23 | private DeviceInfo mDevInfo; // 设备信息
24 | private static FoucsHandle mUpdateDevice;
25 | private static ApkInstallBuffer mInstallBuffer;
26 |
27 |
28 |
29 | public RemoveAppThread( DeviceInfo devInfo) {
30 | mDevInfo = devInfo;
31 | mInstallBuffer = ApkInstallBuffer.getInstance();
32 | mUpdateDevice = FoucsHandle.getInstance();
33 | }
34 |
35 | @Override
36 | public void run() {
37 |
38 | String cmd = null;
39 |
40 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_STATUS);
41 |
42 | try {
43 |
44 | while ( mDevInfo.getQueue().size() > 0) {
45 | String removeApp = mDevInfo.getQueue().take();
46 | System.out.println( " RemoveAppThread removeApp = " + removeApp );
47 |
48 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
49 | + " uninstall " + removeApp ;
50 | System.out.println( " RemoveAppThread cmd = " + cmd );
51 | String result = Function.exec(cmd);
52 |
53 | System.out.println("RemoveAppThread result = " + result
54 | + " cmd = " + cmd );
55 | }
56 |
57 | } catch (InterruptedException e) {
58 |
59 | e.printStackTrace();
60 | }
61 |
62 |
63 |
64 | // cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
65 | // + " shell am startservice --user 0 -a "
66 | // + " com.suitscreen.app.startservice ";
67 | //
68 | // // 判断使用--user 0是否出错
69 | // String result = Function.exec(cmd);
70 | // int res = result.indexOf("Error: Unknown option: --user");
71 | // System.out.println("InstallAppThread result = " + result
72 | // + " res = " + res + " devInfo.devSerial = " + mDevInfo.getDevSerial()
73 | // + " " + mDevInfo.getStatusString() );
74 | //
75 | // if (res != -1) {
76 | // cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
77 | // + " shell am startservice -a "
78 | // + " com.suitscreen.app.startservice ";
79 | //
80 | // result = Function.exec(cmd);
81 | // System.out.println("InstallAppThread Error: Unknown option: --user result = " + result
82 | // + " res = " + res + " devInfo.devSerial = " + mDevInfo.getDevSerial()
83 | // + " " + mDevInfo.getStatusString() );
84 | // }
85 |
86 | // cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
87 | // + " shell am startservice -a "
88 | // + " com.suitscreen.app.startservice ";
89 | //
90 | // String result = Function.exec(cmd);
91 | // System.out.println(" RemoveAppThread result = " + result
92 | // + " devInfo.devSerial = " + mDevInfo.getDevSerial()
93 | // + " " + mDevInfo.getStatusString() );
94 | // mDevInfo.setStatusString(DeviceInfo.FORWARD_PORT_MAP);
95 | //
96 | // cmd = MainBash.ADB_PATH + "adb -s "
97 | // + mDevInfo.getDevSerial() + " forward tcp:"
98 | // + mDevInfo.getMapPort() + " tcp:10086";
99 | //
100 | // result = Function.exec(cmd);
101 | // System.out.println( " RemoveAppThread mDevInfo.getDevSerial() = " + mDevInfo.getDevSerial()
102 | // + " mDevInfo.getMapPort() = " + mDevInfo.getMapPort() );
103 | //
104 | // try {
105 | // mSocket = new Socket(InetAddress.getByName("127.0.0.1"),
106 | // mDevInfo.getMapPort() );
107 | // BufferedOutputStream out = new BufferedOutputStream( mSocket.getOutputStream() );
108 | // BufferedInputStream in = new BufferedInputStream( mSocket.getInputStream() );
109 | //
110 | //
111 | // // 发送指令
112 | // /* 将整数转成4字节byte数组 */
113 | // byte[] cmdLength = new byte[4];
114 | // cmdLength = Tool.intToByte( mDevInfo.CMD_GET_PACKAGENAME );
115 | // out.write( cmdLength );
116 | // out.flush();
117 | //
118 | // byte[] filelength = new byte[4];
119 | // String strFormsocket = readFromSocket(in, filelength);
120 | // System.out.println( " RemoveAppThread strFormsocket = " + strFormsocket );
121 | //
122 | // if ( strFormsocket != null ) {
123 | // String[] removeApps = strFormsocket.split(":");
124 | //
125 | // for ( String removeApp:removeApps ) {
126 | // System.out.println( " RemoveAppThread removeApp = " + removeApp );
127 | // cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
128 | // + " uninstall " + removeApp ;
129 | // System.out.println( " RemoveAppThread cmd = " + cmd );
130 | // result = Function.exec(cmd);
131 | // }
132 | // }
133 | //
134 | // mDevInfo.setStatus( DeviceInfo.STATUS_REMOVE_FINISH );
135 | // mUpdateDevice.handleInfo();
136 | // } catch (UnknownHostException e) {
137 | //
138 | // e.printStackTrace();
139 | // } catch (IOException e) {
140 | //
141 | // e.printStackTrace();
142 | // }
143 | // String packageName = synch2device(CMD_GET_PACKAGENAME, null);
144 |
145 | //System.out.println(" RemoveAppThread packageName = " + packageName);
146 |
147 |
148 | }
149 |
150 | /* 从InputStream流中读数据 */
151 | public static String readFromSocket( InputStream in, byte[] filelength ) {
152 | byte[] filebytes = null;// 文件数据
153 | String msg = null;
154 | try {
155 | // 读文件长度
156 | in.read(filelength);
157 | int filelen = Tool.byteToInt(filelength);// 文件长度从4字节byte[]转成Int
158 | filebytes = new byte[filelen];
159 | int pos = 0;
160 | int rcvLen = 0;
161 | while ( ( rcvLen = in.read( filebytes, pos, filelen - pos ) ) > 0 ) {
162 | pos += rcvLen;
163 | }
164 |
165 | if ( filelen > 0 ) {
166 | msg = new String(filebytes, 0, filelen, "utf-8");
167 | }
168 |
169 | } catch (IOException e1) {
170 |
171 | e1.printStackTrace();
172 | }
173 |
174 | return msg;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/providers/SQLiteContentProvider.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.providers;
2 |
3 | import android.content.ContentProvider;
4 | import android.content.ContentProviderOperation;
5 | import android.content.ContentProviderResult;
6 | import android.content.ContentValues;
7 | import android.content.Context;
8 | import android.content.OperationApplicationException;
9 | import android.database.sqlite.SQLiteDatabase;
10 | import android.database.sqlite.SQLiteOpenHelper;
11 | import android.database.sqlite.SQLiteTransactionListener;
12 | import android.net.Uri;
13 |
14 | import java.util.ArrayList;
15 |
16 | /**
17 | * General purpose {@link ContentProvider} base class that uses SQLiteDatabase for storage.
18 | */
19 | public abstract class SQLiteContentProvider extends ContentProvider
20 | implements SQLiteTransactionListener {
21 |
22 | private static final String TAG = "SQLiteContentProvider";
23 |
24 | private SQLiteOpenHelper mOpenHelper;
25 | private volatile boolean mNotifyChange;
26 | protected SQLiteDatabase mDb;
27 |
28 | private final ThreadLocal mApplyingBatch = new ThreadLocal();
29 | private static final int SLEEP_AFTER_YIELD_DELAY = 4000;
30 |
31 | /**
32 | * Maximum number of operations allowed in a batch between yield points.
33 | */
34 | private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500;
35 |
36 | @Override
37 | public boolean onCreate() {
38 | Context context = getContext();
39 | mOpenHelper = getDatabaseHelper(context);
40 | return true;
41 | }
42 |
43 | protected abstract SQLiteOpenHelper getDatabaseHelper(Context context);
44 |
45 | /**
46 | * The equivalent of the {@link #insert} method, but invoked within a transaction.
47 | */
48 | protected abstract Uri insertInTransaction(Uri url, ContentValues initialValues);
49 |
50 | /**
51 | * The equivalent of the {@link #update} method, but invoked within a transaction.
52 | */
53 | protected abstract int updateInTransaction(Uri url, ContentValues values, String where,
54 | String[] whereArgs);
55 |
56 | /**
57 | * The equivalent of the {@link #delete} method, but invoked within a transaction.
58 | */
59 | protected abstract int deleteInTransaction(Uri url, String where, String[] whereArgs);
60 |
61 | protected abstract void notifyChange();
62 |
63 | protected SQLiteOpenHelper getDatabaseHelper() {
64 | return mOpenHelper;
65 | }
66 |
67 | private boolean applyingBatch() {
68 | return mApplyingBatch.get() != null && mApplyingBatch.get();
69 | }
70 |
71 | @Override
72 | public Uri insert(Uri uri, ContentValues values) {
73 | Uri result = null;
74 | boolean applyingBatch = applyingBatch();
75 | if (!applyingBatch) {
76 | mDb = mOpenHelper.getWritableDatabase();
77 | mDb.beginTransactionWithListener(this);
78 | try {
79 | result = insertInTransaction(uri, values);
80 | if (result != null) {
81 | mNotifyChange = true;
82 | }
83 | mDb.setTransactionSuccessful();
84 | } finally {
85 | mDb.endTransaction();
86 | }
87 |
88 | onEndTransaction();
89 | } else {
90 | result = insertInTransaction(uri, values);
91 | if (result != null) {
92 | mNotifyChange = true;
93 | }
94 | }
95 | return result;
96 | }
97 |
98 | @Override
99 | public int bulkInsert(Uri uri, ContentValues[] values) {
100 | int numValues = values.length;
101 | mDb = mOpenHelper.getWritableDatabase();
102 | mDb.beginTransactionWithListener(this);
103 | try {
104 | for (int i = 0; i < numValues; i++) {
105 | Uri result = insertInTransaction(uri, values[i]);
106 | if (result != null) {
107 | mNotifyChange = true;
108 | }
109 | mDb.yieldIfContendedSafely();
110 | }
111 | mDb.setTransactionSuccessful();
112 | } finally {
113 | mDb.endTransaction();
114 | }
115 |
116 | onEndTransaction();
117 | return numValues;
118 | }
119 |
120 | @Override
121 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
122 | int count = 0;
123 | boolean applyingBatch = applyingBatch();
124 | if (!applyingBatch) {
125 | mDb = mOpenHelper.getWritableDatabase();
126 | mDb.beginTransactionWithListener(this);
127 | try {
128 | count = updateInTransaction(uri, values, selection, selectionArgs);
129 | if (count > 0) {
130 | mNotifyChange = true;
131 | }
132 | mDb.setTransactionSuccessful();
133 | } finally {
134 | mDb.endTransaction();
135 | }
136 |
137 | onEndTransaction();
138 | } else {
139 | count = updateInTransaction(uri, values, selection, selectionArgs);
140 | if (count > 0) {
141 | mNotifyChange = true;
142 | }
143 | }
144 |
145 | return count;
146 | }
147 |
148 | @Override
149 | public int delete(Uri uri, String selection, String[] selectionArgs) {
150 | int count = 0;
151 | boolean applyingBatch = applyingBatch();
152 | if (!applyingBatch) {
153 | mDb = mOpenHelper.getWritableDatabase();
154 | mDb.beginTransactionWithListener(this);
155 | try {
156 | count = deleteInTransaction(uri, selection, selectionArgs);
157 | if (count > 0) {
158 | mNotifyChange = true;
159 | }
160 | mDb.setTransactionSuccessful();
161 | } finally {
162 | mDb.endTransaction();
163 | }
164 |
165 | onEndTransaction();
166 | } else {
167 | count = deleteInTransaction(uri, selection, selectionArgs);
168 | if (count > 0) {
169 | mNotifyChange = true;
170 | }
171 | }
172 | return count;
173 | }
174 |
175 | @Override
176 | public ContentProviderResult[] applyBatch(ArrayList operations)
177 | throws OperationApplicationException {
178 | int ypCount = 0;
179 | int opCount = 0;
180 | mDb = mOpenHelper.getWritableDatabase();
181 | mDb.beginTransactionWithListener(this);
182 | try {
183 | mApplyingBatch.set(true);
184 | final int numOperations = operations.size();
185 | final ContentProviderResult[] results = new ContentProviderResult[numOperations];
186 | for (int i = 0; i < numOperations; i++) {
187 | if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) {
188 | throw new OperationApplicationException(
189 | "Too many content provider operations between yield points. "
190 | + "The maximum number of operations per yield point is "
191 | + MAX_OPERATIONS_PER_YIELD_POINT, ypCount);
192 | }
193 | final ContentProviderOperation operation = operations.get(i);
194 | if (i > 0 && operation.isYieldAllowed()) {
195 | opCount = 0;
196 | if (mDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) {
197 | ypCount++;
198 | }
199 | }
200 | results[i] = operation.apply(this, results, i);
201 | }
202 | mDb.setTransactionSuccessful();
203 | return results;
204 | } finally {
205 | mApplyingBatch.set(false);
206 | mDb.endTransaction();
207 | onEndTransaction();
208 | }
209 | }
210 |
211 | public void onBegin() {
212 | onBeginTransaction();
213 | }
214 |
215 | public void onCommit() {
216 | beforeTransactionCommit();
217 | }
218 |
219 | public void onRollback() {
220 | // not used
221 | }
222 |
223 | protected void onBeginTransaction() {
224 | }
225 |
226 | protected void beforeTransactionCommit() {
227 | }
228 |
229 | protected void onEndTransaction() {
230 | if (mNotifyChange) {
231 | mNotifyChange = false;
232 | notifyChange();
233 | }
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/ui/MainBash.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall.ui;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 |
10 |
11 | import com.suitscreen.batchinstall.ApkInstallBuffer;
12 | import com.suitscreen.batchinstall.ApkInstallInfo;
13 | import com.suitscreen.batchinstall.Config;
14 | import com.suitscreen.batchinstall.DeviceBuffer;
15 | import com.suitscreen.batchinstall.DeviceInfo;
16 | import com.suitscreen.batchinstall.process.FoucsHandle;
17 |
18 | public class MainBash {
19 | public static final String ADB_PATH = "/work/adb/";
20 | private static volatile int mPort = 10081;
21 | private static DeviceBuffer mDevBuffer;
22 | private static ApkInstallBuffer mInstallBuffer;
23 | private static FoucsHandle mUpdateDevice;
24 | private static String picturePathName = "suitscreen";
25 | /**
26 | * @param args
27 | */
28 | public static void main(String[] args) {
29 | //String pictureDir = null;
30 | String installPath = null;
31 |
32 | if (args.length == 0) {
33 | System.out.println("请输入安装包路径");
34 | return;
35 | }
36 |
37 | mDevBuffer = DeviceBuffer.getInstance();
38 | mInstallBuffer = ApkInstallBuffer.getInstance();
39 | mUpdateDevice = FoucsHandle.getInstance();
40 |
41 | detectDeviceNo();
42 |
43 | DeviceInfo deviceInfo;
44 |
45 | for (int index = 0; index < mDevBuffer.size(); index++) {
46 | deviceInfo = mDevBuffer.get(index);
47 | System.out.println("deviceInfo.devSerial = " + deviceInfo.getDevSerial()
48 | + " deviceInfo.status = " + deviceInfo.getStatus());
49 | }
50 |
51 | for (int index = 0; index < args.length; index++) {
52 | ApkInstallInfo installInfo = new ApkInstallInfo();
53 | installPath = args[index];
54 |
55 | if (!installPath.endsWith(".apk") ) {
56 | System.out.println("请选择android安装包");
57 | continue;
58 | }
59 |
60 | File installFile = new File(installPath);
61 |
62 | if ( !installFile.exists() ) {
63 | System.out.println("没有此文件");
64 | continue;
65 | }
66 |
67 |
68 | installInfo.setApkName( installFile.getName() );
69 | installInfo.setApkPath( installFile.getPath() );
70 | installInfo.setInstallStatus(ApkInstallInfo.INSTALL_PREPARE);
71 | mInstallBuffer.add(installInfo);
72 | System.out.println(" args[index] = " + args[index] + " installFile.getName() = "
73 | + installFile.getName() + " installFile.getPath() = " + installFile.getPath());
74 | }
75 |
76 | for (int index = 0; index < mDevBuffer.size(); index++) {
77 | deviceInfo = mDevBuffer.get(index);
78 | System.out.println("deviceInfo.devSerial = " + deviceInfo.getDevSerial()
79 | + " deviceInfo.status = " + deviceInfo.getStatus() );
80 | }
81 |
82 | // settingInstallPath();
83 |
84 |
85 |
86 |
87 |
88 | // mDetectDeviceThread = new DetectDeviceThread();
89 | // mDetectDeviceThread.start();
90 | // detectDeviceNo();
91 | mUpdateDevice.handleInfo();
92 |
93 | }
94 |
95 |
96 | /**
97 | * 执行adb命令,检测已连接的设备
98 | *
99 | * @param cmd
100 | * , 要执行的命令
101 | * @return 命令执行的返回字符串
102 | */
103 | private static void detectDeviceNo() {
104 |
105 | Process process = null;
106 | InputStreamReader in = null;
107 | BufferedReader reader = null;
108 |
109 | try {
110 |
111 | process = Runtime.getRuntime().exec( new String[] { MainBash.ADB_PATH + "adb", "devices"}); // 启动另一个进程来执行命令
112 | in = new InputStreamReader( process.getInputStream() );
113 | reader = new BufferedReader(in);
114 |
115 | String line = null;
116 |
117 | while ( ( line = reader.readLine() ) != null ) {
118 |
119 | System.out.println(" MainBash line = " + line);
120 |
121 | if ( line.contains("List of devices") ) {
122 | }
123 | // 返回“ADB server didn't ACK”,则认为adb服务已经崩溃
124 | else if (line.contains("ADB server didn't ACK")) {
125 |
126 | } else {
127 |
128 | int index = line.indexOf("device"); // 判断连线的手机
129 | if ( mPort++ > 19999 ) {
130 | mPort = 10081;
131 | }
132 |
133 | if (index > 0) {
134 | String serial = line.substring(0, index - 1);
135 | mDevBuffer.add(new DeviceInfo(serial,
136 | DeviceInfo.STATUS_PLUGIN,
137 | mPort) );
138 | } else {
139 | index = line.indexOf("offline");
140 | if (index > 0) {
141 | String serial = line.substring(0, index - 1);
142 | mDevBuffer.add(new DeviceInfo(serial,
143 | DeviceInfo.STATUS_OFFLINE,
144 | mPort) );
145 | }
146 | }
147 | }
148 | }
149 | // 刷新设备列表
150 |
151 | } catch (Exception e) {
152 | e.printStackTrace();
153 | } finally {
154 | if (process != null) {
155 | try {
156 | reader.close();
157 | in.close();
158 | } catch (IOException e) {
159 | e.printStackTrace();
160 | }
161 |
162 | process.destroy();
163 | }
164 | }
165 | }
166 |
167 | private static void settingInstallPath() {
168 | String SysType = System.getProperties().getProperty(
169 | "os.name");
170 |
171 | if (SysType.startsWith("win") || SysType.startsWith("Win")) {
172 | Config.setPicturePath("C:" + File.separator + picturePathName );
173 |
174 | // 安装adb, 将adb相关文件copy到system32文件夹
175 | String system32 = System.getenv("SystemRoot")
176 | + File.separator + "System32" + File.separator;
177 | try {
178 |
179 | File adbFile = new File(system32 + "adb.exe");
180 | if (!adbFile.exists()) {
181 | FileInputStream input = new FileInputStream(
182 | "adb/adb.exe");
183 | FileOutputStream output = new FileOutputStream(
184 | system32 + "adb.exe");
185 | int in = input.read();
186 | while (in != -1) {
187 | output.write(in);
188 | in = input.read();
189 | }
190 | input.close();
191 | output.close();
192 | }
193 |
194 | File AdbWinApi = new File(system32
195 | + "AdbWinApi.dll");
196 |
197 | if ( !AdbWinApi.exists() ) {
198 | FileInputStream input = new FileInputStream(
199 | "adb/AdbWinApi.dll");
200 | FileOutputStream output = new FileOutputStream(
201 | system32 + "AdbWinApi.dll");
202 | int in = input.read();
203 | while (in != -1) {
204 | output.write(in);
205 | in = input.read();
206 | }
207 | input.close();
208 | output.close();
209 | }
210 |
211 | File AdbWinUsbApi = new File(system32
212 | + "AdbWinUsbApi.dll");
213 | if (!AdbWinUsbApi.exists()) {
214 | FileInputStream input = new FileInputStream(
215 | "adb/AdbWinUsbApi.dll");
216 | FileOutputStream output = new FileOutputStream(
217 | system32 + "AdbWinUsbApi.dll");
218 | int in = input.read();
219 | while (in != -1) {
220 | output.write(in);
221 | in = input.read();
222 | }
223 | input.close();
224 | output.close();
225 | }
226 |
227 | } catch (IOException e) {
228 | System.out.println(e.toString());
229 | }
230 | } else {
231 | String userHome = System.getProperties().getProperty(
232 | "user.home");
233 | Config.setPicturePath(userHome + File.separator + picturePathName );
234 | }
235 |
236 | File picturefile = new File( Config.getPicturePath() );
237 |
238 | if ( !picturefile.exists() ) {
239 | picturefile.mkdirs();
240 | }
241 |
242 | System.out.println("MainBash fileDir = " + Config.getPicturePath() );
243 | }
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/providers/SuitProvider.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.providers;
2 |
3 |
4 |
5 | import android.content.ContentProviderOperation;
6 | import android.content.ContentProviderResult;
7 | import android.content.ContentResolver;
8 | import android.content.ContentUris;
9 | import android.content.ContentValues;
10 | import android.content.Context;
11 | import android.content.OperationApplicationException;
12 | import android.content.UriMatcher;
13 | import android.database.Cursor;
14 | import android.database.DatabaseUtils;
15 | import android.database.sqlite.SQLiteDatabase;
16 | import android.database.sqlite.SQLiteOpenHelper;
17 | import android.database.sqlite.SQLiteQueryBuilder;
18 | import android.net.Uri;
19 | import android.util.Log;
20 |
21 | import java.text.ParseException;
22 | import java.text.SimpleDateFormat;
23 | import java.util.ArrayList;
24 | import java.util.Date;
25 |
26 | import com.suitscreen.app.mobiles.SocketService;
27 | import com.suitscreen.app.providers.SuitScreen.InstalledApp;
28 |
29 |
30 |
31 |
32 | public class SuitProvider extends SQLiteContentProvider {
33 | private final static String TAG = "BreezingProvider";
34 | public static String TABLE_INSTALL_APP = "install_app";
35 |
36 | private SQLiteOpenHelper mOpenHelper;
37 |
38 | @Override
39 | public String getType(Uri url) {
40 | Log.d(TAG, " getType uri = " + url);
41 | // Generate the body of the query.
42 | int match = sURLMatcher.match(url);
43 | switch (match) {
44 | case SUIT_APP_INSTALL:
45 | return InstalledApp.CONTENT_TYPE;
46 | case SUIT_APP_INSTALL_ID:
47 | return InstalledApp.CONTENT_ITEM_TYPE;
48 | default:
49 | return null;
50 | }
51 | }
52 |
53 | private void notifyChange(Uri uri) {
54 | Log.d(TAG, " notifyChange uri = " + uri);
55 | ContentResolver cr = getContext().getContentResolver();
56 | cr.notifyChange(uri, null);
57 | }
58 |
59 | @Override
60 | public boolean onCreate() {
61 | super.onCreate();
62 | try {
63 | return initialize();
64 | } catch (RuntimeException e) {
65 | Log.e(TAG, "Cannot start provider", e);
66 | return false;
67 | }
68 | }
69 |
70 | private boolean initialize() {
71 |
72 | mOpenHelper = getDatabaseHelper();
73 | mDb = mOpenHelper.getWritableDatabase();
74 | return (mDb != null);
75 | }
76 |
77 | @Override
78 | public Cursor query(Uri url, String[] projectionIn, String selection,
79 | String[] selectionArgs, String sort) {
80 | SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
81 | // Generate the body of the query.
82 | int match = sURLMatcher.match(url);
83 | switch (match) {
84 | case SUIT_APP_INSTALL:
85 | qb.setTables(TABLE_INSTALL_APP);
86 | break;
87 | case SUIT_APP_INSTALL_ID:
88 | qb.setTables(TABLE_INSTALL_APP);
89 | qb.appendWhere("( _id = " + url.getPathSegments().get(1) + ")");
90 | break;
91 |
92 |
93 | default:
94 | Log.e(TAG, "query: invalid request: " + url);
95 | return null;
96 | }
97 |
98 | String finalSortOrder = InstalledApp.DEFAULT_SORT_ORDER;
99 |
100 |
101 | SQLiteDatabase db = mOpenHelper.getReadableDatabase();
102 | Cursor ret = qb.query(db, projectionIn, selection,
103 | selectionArgs, null, null, finalSortOrder);
104 |
105 | Log.d(SocketService.TAG, " query selection = " + selection.toString() + " selectionArgs = " + selectionArgs.toString() );
106 | ret.setNotificationUri(getContext().getContentResolver(), url);
107 | return ret;
108 | }
109 |
110 | @Override
111 | public int delete(Uri url, String where, String[] whereArgs) {
112 | return super.delete(url, where, whereArgs);
113 | }
114 |
115 | @Override
116 | public Uri insert(Uri url, ContentValues initialValues) {
117 | return super.insert(url, initialValues);
118 | }
119 |
120 | @Override
121 | public int update(Uri url, ContentValues values, String where,
122 | String[] whereArgs) {
123 | Log.d(SocketService.TAG, " update where = " + where.toString() + " whereArgs = " + whereArgs.toString() );
124 | return super.update(url, values, where, whereArgs);
125 | }
126 |
127 | @Override
128 | public ContentProviderResult[] applyBatch(ArrayList operations)
129 | throws OperationApplicationException {
130 | Log.d(TAG, " applyBatch ");
131 | return super.applyBatch(operations);
132 | }
133 |
134 | @Override
135 | protected SQLiteOpenHelper getDatabaseHelper(Context context) {
136 | return SuitDatabaseHelper.getInstance(getContext());
137 | }
138 |
139 | @Override
140 | protected Uri insertInTransaction(Uri url, ContentValues initialValues) {
141 | long rowID = 0;
142 | int match = sURLMatcher.match(url);
143 | String dateStr = simpleDateFormat("yyyyMMddHHmmss");
144 |
145 | initialValues.put(InstalledApp.DATE, dateStr);
146 |
147 |
148 | switch (match) {
149 | case SUIT_APP_INSTALL:
150 | rowID = mDb.insert(TABLE_INSTALL_APP, InstalledApp.PACKAGE_NAME, initialValues);
151 | break;
152 | default:
153 | Log.e(TAG, "insert: invalid request: " + url);
154 | return null;
155 | }
156 |
157 | if (rowID > 0) {
158 | Uri uri = ContentUris.withAppendedId(url, rowID);
159 |
160 | if (Log.isLoggable(TAG, Log.VERBOSE)) {
161 | Log.d(TAG, "insert " + uri + " succeeded");
162 | }
163 | notifyChange(url);
164 | return uri;
165 | } else {
166 | Log.e(TAG,"insert: failed! " + initialValues.toString() );
167 | }
168 |
169 | return null;
170 | }
171 |
172 |
173 |
174 | @Override
175 | protected int updateInTransaction(Uri url, ContentValues values, String where,
176 | String[] whereArgs) {
177 | int count = 0;
178 | String table = null;
179 | String extraWhere = null;
180 |
181 | int match = sURLMatcher.match(url);
182 | switch (match) {
183 | case SUIT_APP_INSTALL:
184 | table = TABLE_INSTALL_APP;
185 | break;
186 | case SUIT_APP_INSTALL_ID:
187 | table = TABLE_INSTALL_APP;
188 | extraWhere = "_id=" + url.getPathSegments().get(1);
189 | break;
190 | default:
191 | throw new UnsupportedOperationException(
192 | "URI " + url + " not supported");
193 | }
194 |
195 | if (extraWhere != null) {
196 | where = DatabaseUtils.concatenateWhere(where, extraWhere);
197 | }
198 |
199 | Log.d(TAG, "update where = " + where);
200 | count = mDb.update(table, values, where, whereArgs);
201 |
202 | if (count > 0) {
203 | Log.d(TAG, "update " + url + " succeeded");
204 | notifyChange(url);
205 | }
206 |
207 | return count;
208 | }
209 |
210 | @Override
211 | protected int deleteInTransaction(Uri url, String where,
212 | String[] whereArgs) {
213 | int count = 0;
214 | int match = sURLMatcher.match(url);
215 |
216 |
217 | switch (match) {
218 | case SUIT_APP_INSTALL:
219 |
220 | count = mDb.delete(TABLE_INSTALL_APP, where, whereArgs);
221 | break;
222 | case SUIT_APP_INSTALL_ID:
223 |
224 | int appId;
225 |
226 | try {
227 | appId = Integer.parseInt( url.getPathSegments().get(1) );
228 | } catch (Exception e) {
229 | throw new IllegalArgumentException(
230 | "Bad message id: " + url.getPathSegments().get(1));
231 | }
232 |
233 | where = DatabaseUtils.concatenateWhere("_id = " + appId, where);
234 | count = mDb.delete(TABLE_INSTALL_APP, where, whereArgs);
235 | break;
236 | default:
237 | Log.e(TAG, "query: invalid request: " + url);
238 | }
239 |
240 | return count;
241 | }
242 |
243 | @Override
244 | protected void notifyChange() {
245 | ContentResolver cr = getContext().getContentResolver();
246 | //cr.notifyChange(uri, null);
247 | }
248 |
249 | private static final int SUIT_APP_INSTALL = 1;
250 | private static final int SUIT_APP_INSTALL_ID = 2;
251 |
252 |
253 | private static final UriMatcher sURLMatcher =
254 | new UriMatcher(UriMatcher.NO_MATCH);
255 |
256 | static {
257 | sURLMatcher.addURI(SuitScreen.AUTHORITY, "install", SUIT_APP_INSTALL);
258 | sURLMatcher.addURI(SuitScreen.AUTHORITY, "install/#", SUIT_APP_INSTALL_ID);
259 |
260 | }
261 |
262 |
263 | private String simpleDateFormat(String format) {
264 | SimpleDateFormat sdf = new SimpleDateFormat(format);
265 | String strDate = sdf.format(new Date());
266 | Log.d(TAG, "format = " + format + " sdf.format(new Date()) = " + sdf.format(new Date()));
267 | Date date = null;
268 | try {
269 | date = sdf.parse(strDate);
270 | } catch (ParseException e) {
271 | e.printStackTrace();
272 | }
273 |
274 | Log.d(TAG, " simpleDateFormat date = " + date + " strDate = " + strDate);
275 | // int intDate = String.v.parseInt(strDate);
276 | // Log.d(TAG, "simpleDateFormat longDate = " + intDate);
277 | // return intDate;
278 | return strDate;
279 | }
280 |
281 | }
282 |
--------------------------------------------------------------------------------
/SuitScreen/src/com/suitscreen/batchinstall/process/InstallAppThread.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.batchinstall.process;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.net.InetAddress;
8 | import java.net.Socket;
9 | import java.net.UnknownHostException;
10 |
11 | import com.suitscreen.batchinstall.ApkInstallBuffer;
12 | import com.suitscreen.batchinstall.ApkInstallInfo;
13 | import com.suitscreen.batchinstall.DeviceInfo;
14 | import com.suitscreen.batchinstall.Function;
15 | import com.suitscreen.batchinstall.Tool;
16 | import com.suitscreen.batchinstall.ui.MainBash;
17 |
18 |
19 | public class InstallAppThread implements Runnable {
20 | private Socket mSocket; // Socket客户端
21 | private DeviceInfo mDevInfo; // 设备信息
22 | private static FoucsHandle mUpdateDevice;
23 | private static ApkInstallBuffer mInstallBuffer;
24 |
25 |
26 | public InstallAppThread( DeviceInfo devInfo) {
27 | mDevInfo = devInfo;
28 | mInstallBuffer = ApkInstallBuffer.getInstance();
29 | mUpdateDevice = FoucsHandle.getInstance();
30 | }
31 |
32 | public void run() {
33 |
34 | // 先执行命令
35 | BufferedOutputStream out = null;
36 | BufferedInputStream in = null;
37 | try {
38 | String cmd = null;
39 |
40 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_STATUS);
41 |
42 | // cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial()
43 | // + " install -r SuitScreen_Android.apk";
44 | //// // 判断是否安装成功
45 | //// String result = Function.exec(cmd);
46 | //
47 | //
48 | // int res = result.indexOf("Failure");
49 | // System.out.println("InstallAppThread result = " + result
50 | // + " res = " + res + " devInfo.devSerial = " + devInfo.getDevSerial()
51 | // + " " + devInfo.statusString );
52 | //
53 | // if (res != -1) {
54 | // cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial()
55 | // + " uninstall com.suitscreen.suitscreen";
56 | // Function.exec(cmd);
57 | // cmd = MainBash.ADB_PATH + "adb -s " + devInfo.getDevSerial()
58 | // + " install -r SuitScreen_Android.apk";
59 | // Function.exec(cmd);
60 | // }
61 | mDevInfo.setStatusString(DeviceInfo.LUNCHER_PROGRAM_STATUS);
62 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
63 | + " shell am startservice --user 0 -a "
64 | + " com.suitscreen.app.startservice ";
65 |
66 | // 判断使用--user 0是否出错
67 | String result = Function.exec(cmd);
68 | int res = result.indexOf("Error: Unknown option: --user");
69 | System.out.println("InstallAppThread result = " + result
70 | + " res = " + res + " devInfo.devSerial = " + mDevInfo.getDevSerial()
71 | + " " + mDevInfo.getStatusString() );
72 |
73 | if (res != -1) {
74 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
75 | + " shell am startservice -a "
76 | + "com.suitscreen.app.startservice ";
77 | result = Function.exec(cmd);
78 | System.out.println("InstallAppThread Error: Unknown option: --user result = " + result
79 | + " res = " + res + " devInfo.devSerial = " + mDevInfo.getDevSerial()
80 | + " " + mDevInfo.getStatusString() );
81 | }
82 |
83 | // cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
84 | // + " shell am startservice -a "
85 | // + " com.suitscreen.app.startservice ";
86 |
87 | // String result = Function.exec(cmd);
88 | // System.out.println(" InstallAppThread result = " + result
89 | // + " devInfo.devSerial = " + mDevInfo.getDevSerial()
90 | // + " " + mDevInfo.getStatusString() );
91 |
92 |
93 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
94 | + " shell am broadcast -a NotifyServiceStop";
95 | result = Function.exec(cmd);
96 | System.out.println( " InstallAppThread NotifyServiceStop " );
97 | mDevInfo.setStatusString(DeviceInfo.FORWARD_PORT_MAP);
98 | cmd = MainBash.ADB_PATH + "adb -s "
99 | + mDevInfo.getDevSerial() + " forward tcp:"
100 | + mDevInfo.getMapPort() + " tcp:10086";
101 |
102 | result = Function.exec(cmd);
103 | System.out.println( " InstallAppThread mDevInfo.getDevSerial() = " + mDevInfo.getDevSerial()
104 | + " mDevInfo.getMapPort() = " + mDevInfo.getMapPort() );
105 |
106 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial()
107 | + " shell am broadcast -a NotifyServiceStart";
108 | result = Function.exec(cmd);
109 | System.out.println( " InstallAppThread NotifyServiceStart " );
110 |
111 |
112 | //
113 | //
114 | //
115 | // socket = new Socket(InetAddress.getByName("127.0.0.1"),
116 | // devInfo.mapPort);
117 | // devInfo.statusString = "正在和手机客户端通讯";
118 |
119 | // // 发送获取手机型号的指令
120 | // // 手机型号有空格则用“—”代替
121 | // devInfo.setDevModel( synch2device(0x01, null).trim() );
122 | // if ( (devInfo.getDevModel() != null )
123 | // && (devInfo.getDevModel().length() != 0 ) ) {
124 | // devInfo.setDevModel( devInfo.getDevModel().replace(" ", "-") );
125 | // }
126 |
127 | // System.out.println("devInfo.devModel = " + devInfo.devModel );
128 | // // 发送获取手机IMEI号的指令
129 | // devInfo.imei = synch2device(0x02, null);
130 | // System.out.println(" devInfo.imei = " + devInfo.imei);
131 | //
132 | // String displayMetrics = synch2device(0x03, null);
133 | //
134 | // if ( (displayMetrics != null )
135 | // && (displayMetrics.length() != 0 ) ) {
136 | // String[] wh = displayMetrics.split("-");
137 | //
138 | // devInfo.screenWidth = Integer.parseInt(wh[0]);
139 | // devInfo.screenHeight = Integer.parseInt(wh[1]);
140 | // }
141 | //
142 | // System.out.println("displayMetrics = " + displayMetrics );
143 |
144 | // String fileDir;
145 | // // pc端创建存储文件夹
146 | // if ( devInfo.getDevModel().length() > 0) {
147 | // fileDir = Config.getPicturePath() + File.separator
148 | // + devInfo.getDevModel();
149 | // } else {
150 | // fileDir = Config.getPicturePath() + File.separator
151 | // + "devModel";
152 | // }
153 | //
154 | //
155 | // File filePath = new File(fileDir);
156 | //
157 | // System.out.println("InstallAppThread fileDir = " + fileDir );
158 | //
159 | // devInfo.statusString = "创建文件夹";
160 | // if (!filePath.exists() ) {
161 | // filePath.mkdirs();
162 | // }
163 |
164 |
165 | // 通知终端开始安装
166 | mDevInfo.setStatusString(DeviceInfo.START_INSTALL_PROGRAM_STATUS );
167 | cmd = MainBash.ADB_PATH + "adb -s " + mDevInfo.getDevSerial() + " install -r "
168 | + mDevInfo.getApkPath();
169 |
170 | String installResult = Function.exec(cmd);
171 | int install_res = installResult.indexOf("Failure");
172 |
173 | System.out.println("InstallAppThread installResult = " + installResult
174 | + " install_res = " + install_res + " devInfo.devSerial = " + mDevInfo.getDevSerial()
175 | + " " + mDevInfo.getStatusString() );
176 |
177 | if ( install_res != -1 ) {
178 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_ERRO);
179 | changeApkInstallStatus( ApkInstallInfo.INSTALL_ERROR );
180 | mDevInfo.setStatus( DeviceInfo.STATUS_END_INSTALL );
181 | mUpdateDevice.handleInfo();
182 | return;
183 | }
184 |
185 |
186 | // int index = 0;
187 | // while ( index < 5) {
188 | // devInfo.statusString = "正在截图";
189 | // Function.screenCap(devInfo);
190 | // Thread.sleep(1000);
191 | // index++;
192 | // }
193 |
194 | // check activity started
195 | // for (;;) {
196 | // if ( "started".equals(synch2device(0x04, null).trim() ) ) {
197 | // devInfo.statusString = "开始截图";
198 | // int i = 0;
199 | // while (i < 5) {
200 | // devInfo.statusString = "正在截图";
201 | // Function.screenCap(devInfo);
202 | // Thread.sleep(1000);
203 | // i++;
204 | // }
205 | //
206 | // devInfo.statusString = "截图完毕";
207 | // break;
208 | // }
209 | // }
210 |
211 | // // 操作完成后删除守护软件
212 | // cmd = "adb -s " + devInfo.devSerial +
213 | // " uninstall com.suitscreen.suitscreen";
214 | // Function.exec(cmd);
215 |
216 | // 将状态设置为完成安装
217 | mSocket = new Socket(InetAddress.getByName("127.0.0.1"),
218 | mDevInfo.getMapPort() );
219 | out = new BufferedOutputStream( mSocket.getOutputStream() );
220 | in = new BufferedInputStream( mSocket.getInputStream() );
221 |
222 | // 发送指令
223 | /* 将整数转成4字节byte数组 */
224 | byte[] cmdLength = new byte[4];
225 | cmdLength = Tool.intToByte( mDevInfo.CMD_GET_PACKAGENAME );
226 | out.write( cmdLength );
227 | out.flush();
228 | try {
229 | Thread.sleep(100);
230 | } catch (InterruptedException e1) {
231 | e1.printStackTrace();
232 | }
233 | byte[] filelength = new byte[4];
234 | String strFormsocket = readFromSocket(in, filelength);
235 | System.out.println( " RemoveAppThread strFormsocket = " + strFormsocket );
236 |
237 | if ( strFormsocket != null ) {
238 | try {
239 | mDevInfo.getQueue().put(strFormsocket);
240 | } catch (InterruptedException e) {
241 | e.printStackTrace();
242 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_BREAK_DOWN);
243 | }
244 | }
245 |
246 | changeApkInstallStatus( ApkInstallInfo.INSTALL_FINISH );
247 | mDevInfo.setStatus( DeviceInfo.STATUS_END_INSTALL );
248 | mUpdateDevice.handleInfo();
249 | } catch (UnknownHostException e) {
250 | e.printStackTrace();
251 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_BREAK_DOWN);
252 | } catch (IOException e) {
253 | e.printStackTrace();
254 | mDevInfo.setStatusString(DeviceInfo.INSTALL_PROGRAM_BREAK_DOWN);
255 | } finally {
256 | try {
257 | if ( out != null ) {
258 | out.close();
259 | }
260 |
261 | if ( in != null ) {
262 | in.close();
263 | }
264 | if ( mSocket != null ) {
265 | mSocket.close();
266 | System.out.println("socket.close()");
267 | }
268 | } catch (IOException e) {
269 | System.out.println("TCP 5555" + "ERROR:" + e.toString());
270 | }
271 | }
272 |
273 |
274 | }
275 |
276 | // // 发送获取手机IMEI号的指令
277 | // public void closeSocket() {
278 | // try {
279 | // if (socket != null) {
280 | // socket.close();
281 | // socket = null;
282 | // }
283 | // } catch (Exception e) {
284 | // System.out.println("关闭链路时出错:" + e);
285 | // }
286 | // }
287 |
288 | // private String synch2device(int cmd, byte[] data) throws Exception {
289 | // try {
290 | // int length = 4;
291 | //
292 | // if (data != null) {
293 | // length = length + 4 + data.length;
294 | // }
295 | // // 发送指令
296 | // ByteBuffer bb = ByteBuffer.allocate(length);
297 | // bb.putInt(cmd);
298 | //
299 | // if (data != null) {
300 | // bb.putInt(length);
301 | // bb.put(data);
302 | // }
303 | // socket.getOutputStream().write(bb.array());
304 | // // 收取服务器返回的应答
305 | // byte[] resBytes = new byte[128];
306 | // int numReadedBytes = socket.getInputStream().read(resBytes, 0,
307 | // resBytes.length);
308 | // String rsp = new String(resBytes, 0, numReadedBytes, "utf-8")
309 | // .trim();
310 | // return rsp;
311 | //
312 | // } catch (Exception e) {
313 | // return "";
314 | // }
315 | // }
316 |
317 | private void changeApkInstallStatus(int installStatus) {
318 |
319 | for ( int index = 0; index < mInstallBuffer.size(); index++ ) {
320 |
321 | if ( mInstallBuffer.get(index).getApkPath().equals( mDevInfo.getApkPath() ) ) {
322 | mInstallBuffer.get(index).setInstallStatus(installStatus);
323 | }
324 |
325 | }
326 | }
327 |
328 | /* 从InputStream流中读数据 */
329 | public static String readFromSocket( InputStream in, byte[] filelength ) {
330 | byte[] filebytes = null;// 文件数据
331 | String msg = null;
332 | try {
333 | // 读文件长度
334 |
335 | in.read(filelength, 0, filelength.length);
336 | int filelen = Tool.byteToInt(filelength);// 文件长度从4字节byte[]转成Int
337 | filebytes = new byte[filelen];
338 | int pos = 0;
339 | int rcvLen = 0;
340 | while ( ( rcvLen = in.read( filebytes, pos, filelen - pos ) ) > 0 ) {
341 | pos += rcvLen;
342 | }
343 |
344 | if ( filelen > 0 ) {
345 | msg = new String(filebytes, 0, filelen, "utf-8");
346 | }
347 |
348 | } catch (IOException e1) {
349 |
350 | e1.printStackTrace();
351 | }
352 |
353 | return msg;
354 | }
355 |
356 | }
--------------------------------------------------------------------------------
/SuitScreenMobile/src/com/suitscreen/app/mobiles/SocketService.java:
--------------------------------------------------------------------------------
1 | package com.suitscreen.app.mobiles;
2 |
3 |
4 | import java.io.BufferedInputStream;
5 | import java.io.BufferedOutputStream;
6 | import java.io.IOException;
7 | import java.net.ServerSocket;
8 | import java.net.Socket;
9 | import java.nio.ByteBuffer;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | import com.suitscreen.app.R;
14 | import com.suitscreen.app.providers.SuitScreen;
15 | import com.suitscreen.app.providers.SuitScreen.InstalledApp;
16 |
17 |
18 | import android.app.ActivityManager;
19 | import android.app.Service;
20 | import android.content.BroadcastReceiver;
21 | import android.content.ComponentName;
22 | import android.content.ContentProviderOperation;
23 | import android.content.ContentResolver;
24 | import android.content.Context;
25 | import android.content.Intent;
26 | import android.content.IntentFilter;
27 | import android.content.pm.ResolveInfo;
28 | import android.database.Cursor;
29 | import android.os.Build;
30 | import android.os.IBinder;
31 | import android.util.Log;
32 |
33 | public class SocketService extends Service {
34 | public static final String TAG = "SocketService";
35 |
36 | private static final int SERVER_PORT = 10086;
37 |
38 | private static final String SERVICE_START = "started";
39 | private static final String SERVICE_NO_START = "not start";
40 | private static final String SERVICE_EXIT = "exit";
41 |
42 | private ServerSocket mServerSocket;
43 | private SysBroadcastReceiver mSysBroadcastReceiver;
44 | private Socket mSocket;
45 | private ContentResolver mContentResolver;
46 | private Thread mSocketAcceptThread;
47 |
48 | private static boolean isActivityStart = false;
49 | private static String mPackageName;
50 | private static String mClassName;
51 |
52 | private volatile boolean mInterrupted;
53 |
54 | private BufferedOutputStream mOutput;
55 | private BufferedInputStream mInput;
56 |
57 | public static final int CMD_GET_MODEL = 0x01;
58 | public static final int CMD_CHECK_ACTIVITY_START = 0x04;
59 | public static final int CMD_GET_PACKAGENAME = 0x05;
60 | public static final int CMD_GET_ALL_PACKAGENAME = 0x06;
61 | public static final int CMD_EXIT = 0x09;
62 |
63 |
64 | // public static String imei = "";
65 |
66 | private static final String[] PROJECTION_INSTALL_APP = new String[] {
67 | InstalledApp._ID , // 0
68 | InstalledApp.PACKAGE_NAME // 1
69 | };
70 |
71 |
72 |
73 | private static final int PACKAGE_NAME_INDEX = 1;
74 |
75 | @Override
76 | public void onCreate() {
77 | super.onCreate();
78 |
79 | // TelephonyManager mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
80 | // imei = mTm.getDeviceId();
81 | Log.d(TAG, " SocketService onCreate");
82 | mSysBroadcastReceiver = new SysBroadcastReceiver();
83 | mContentResolver = this.getContentResolver();
84 | IntentFilter filter = new IntentFilter();
85 | filter.addAction(Intent.ACTION_PACKAGE_ADDED);
86 | filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
87 | filter.addDataScheme("package");
88 | registerReceiver(mSysBroadcastReceiver, filter);
89 | start();
90 | }
91 |
92 | private synchronized boolean start( ) {
93 |
94 | if (mSocketAcceptThread == null) {
95 | mSocketAcceptThread = new Thread(TAG) {
96 | public void run() {
97 | mInterrupted = false;
98 |
99 | try {
100 | Log.d(TAG, "Create TCP ServerSocket before mInterrupted = " + mInterrupted);
101 | mServerSocket = new ServerSocket(SERVER_PORT);
102 | Log.d(TAG, "Create TCP ServerSocket after mInterrupted = " + mInterrupted);
103 | } catch (IOException e) {
104 | Log.e(TAG, "Error listing on port" + SERVER_PORT);
105 | mInterrupted = true;
106 | }
107 |
108 | while (!mInterrupted) {
109 | try {
110 | Log.d( TAG, " mServerSocket before mSocket = " + mSocket + " mInterrupted = " +mInterrupted );
111 | mSocket = mServerSocket.accept();
112 | mSocket.setSoTimeout(50000);
113 |
114 | Log.d( TAG, " mServerSocket mSocket = " + mSocket + " mInterrupted = " +mInterrupted );
115 | if ( !mSocket.isConnected() ) {
116 | break;
117 | }
118 | mOutput = new BufferedOutputStream( mSocket.getOutputStream() );
119 | mInput = new BufferedInputStream( mSocket.getInputStream() );
120 |
121 | byte[] cmdBytes = new byte[4];
122 | int read = mInput.read( cmdBytes, 0, cmdBytes.length );
123 |
124 | Log.d( TAG, " byteToInt read = " + read );
125 |
126 | if (read == 0) {
127 | continue;
128 | }
129 |
130 | int cmd = Tool.byteToInt(cmdBytes);
131 |
132 | Log.d(TAG, " byteToInt cmd = " + cmd );
133 |
134 |
135 | if ( cmd == CMD_GET_MODEL ) {
136 | mOutput.write(Build.MODEL.getBytes());
137 | mOutput.flush();
138 | } else if (cmd == CMD_CHECK_ACTIVITY_START) {
139 | if (isActivityStart) {
140 | mOutput.write( SERVICE_START.getBytes() );
141 | mOutput.flush();
142 | } else {
143 | mOutput.write( SERVICE_NO_START.getBytes() );
144 | mOutput.flush();
145 | }
146 | } else if ( cmd == CMD_GET_PACKAGENAME ) {
147 | Log.d(TAG, " CMD_GET_PACKAGENAME cmd = " + cmd + " mPackageName = " + mPackageName );
148 | /* 将整数转成4字节byte数组 */
149 | byte[] filelength = new byte[4];
150 | if ( ( mPackageName != null )
151 | && ( mPackageName.length() > 0) ) {
152 | filelength = Tool.intToByte( mPackageName.length() );
153 | mOutput.write( filelength );
154 | mOutput.flush();
155 | mOutput.write( mPackageName.getBytes() );
156 | mOutput.flush();
157 | }
158 | } else if ( cmd == CMD_GET_ALL_PACKAGENAME ) {
159 | String packageName = queryAllPackageName();
160 | Log.d(TAG, " CMD_GET_ALL_PACKAGENAME cmd = " + cmd + " packageName = " + packageName );
161 | /* 将整数转成4字节byte数组 */
162 | byte[] filelength = new byte[4];
163 |
164 | if ( ( packageName != null )
165 | && ( packageName.length() > 0) ) {
166 | filelength = Tool.intToByte( packageName.length() );
167 | mOutput.write( filelength );
168 | mOutput.flush();
169 | mOutput.write( packageName.getBytes() );
170 | mOutput.flush();
171 | }
172 |
173 | } else if (cmd == CMD_EXIT) {
174 | mOutput.write( SERVICE_EXIT.getBytes() );
175 | mOutput.flush();
176 | mInterrupted = false;
177 | }
178 |
179 | } catch (IOException e) {
180 | e.printStackTrace();
181 | Log.d(TAG, "Error accept connection " + e);
182 | }
183 | }
184 | }
185 | };
186 | }
187 |
188 |
189 | mSocketAcceptThread.start();
190 |
191 | return true;
192 | }
193 |
194 | private class SysBroadcastReceiver extends BroadcastReceiver {
195 | @Override
196 | public void onReceive(Context context, Intent intent) {
197 | String action = intent.getAction();
198 | Log.d(TAG, "MyReceiver onReceive action = " + action);
199 | if ( action.equalsIgnoreCase(Intent.ACTION_PACKAGE_ADDED) ) {
200 |
201 | String str = intent.getDataString();
202 | String[] array = str.split(":");
203 | mPackageName = array[1];
204 | Log.d(TAG, " ACTION_PACKAGE_ADDED InstallAppReceiver mPackageName = " + mPackageName + " str = " + str + " array = " + array.length );
205 | mClassName = getClassName(mPackageName);
206 |
207 | intent = new Intent(Intent.ACTION_MAIN);
208 | intent.addCategory(Intent.CATEGORY_LAUNCHER);
209 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
210 |
211 | ComponentName componentName = new ComponentName(mPackageName, mClassName);
212 | intent.setComponent(componentName);
213 | startActivity(intent);
214 |
215 | try {
216 | Thread.sleep(1000);
217 |
218 | ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
219 | isActivityStart = false;
220 | int index = 0;
221 | while ( ( isActivityStart == false )
222 | && ( index < 5 ) ) {
223 |
224 | ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
225 |
226 | if ( mPackageName.equals( cn.getPackageName() ) ) {
227 | isActivityStart = true;
228 | }
229 |
230 | Thread.sleep(1000);
231 | index++;
232 | }
233 |
234 |
235 | } catch (InterruptedException e) {
236 | e.printStackTrace();
237 | } finally {
238 | handleInstallAppRecord();
239 | }
240 | } else if ( action.equalsIgnoreCase(Intent.ACTION_PACKAGE_REMOVED) ) {
241 | String str = intent.getDataString();
242 | String[] array = str.split(":");
243 | mPackageName = array[1];
244 | Log.d(TAG, " ACTION_PACKAGE_REMOVED InstallAppReceiver mPackageName = " + mPackageName + " str = " + str + " array = " + array.length );
245 | handleRemoveAppRecord();
246 | }
247 | }
248 | }
249 |
250 |
251 | /**
252 | * get apk entry activity
253 | *
254 | * @param packagename
255 | * @return
256 | */
257 | private String getClassName(String packagename) {
258 | Intent localIntent = new Intent(Intent.ACTION_MAIN, null);
259 | localIntent.addCategory(Intent.CATEGORY_LAUNCHER);
260 | List appList = getPackageManager().queryIntentActivities(
261 | localIntent, 0);
262 |
263 | String classname = null;
264 | for ( int index = 0; index < appList.size(); index++ ) {
265 | ResolveInfo info = appList.get(index);
266 | Log.d(TAG, "InstallAppReceiver info.activityInfo.packageName = " + info.activityInfo.packageName
267 | + " info.activityInfo.name = " + info.activityInfo.name );
268 | String packagestr = info.activityInfo.packageName;
269 | if ( packagestr.equals(packagename) ) {
270 | classname = info.activityInfo.name;
271 | }
272 | }
273 | return classname;
274 | }
275 |
276 | @Override
277 | public void onDestroy() {
278 | super.onDestroy();
279 |
280 | stop();
281 | }
282 |
283 | @Override
284 | public IBinder onBind(Intent arg0) {
285 | return null;
286 | }
287 |
288 | public synchronized void stop() {
289 | if (mSocketAcceptThread != null) {
290 | Log.i(TAG, "stopping Accept Thread");
291 |
292 | mInterrupted = true;
293 |
294 | if (mSocket != null ) {
295 | try {
296 | mSocket.close();
297 | } catch (IOException e) {
298 | e.printStackTrace();
299 | }
300 | }
301 |
302 | if (mOutput != null) {
303 | try {
304 | mOutput.close();
305 | } catch (IOException e) {
306 | e.printStackTrace();
307 | }
308 | }
309 |
310 | if (mInput != null) {
311 | try {
312 | mInput.close();
313 | } catch (IOException e) {
314 | e.printStackTrace();
315 | }
316 | }
317 |
318 | if (mServerSocket != null) {
319 | try {
320 | mServerSocket.close();
321 | } catch (IOException e) {
322 | Log.e(TAG, "Error close mTcpServerSocket");
323 | }
324 | }
325 |
326 |
327 |
328 | try {
329 | mSocketAcceptThread.interrupt();
330 | Log.d(TAG, "waiting for thread to terminate");
331 | mSocketAcceptThread.join();
332 | mSocketAcceptThread = null;
333 | } catch (InterruptedException e) {
334 | Log.d(TAG, "Interrupted waiting for Accept Thread to join");
335 | }
336 | }
337 | }
338 |
339 |
340 |
341 | /**
342 | * append new installed application information
343 | *
344 | * @return
345 | */
346 | private String handleInstallAppRecord() {
347 | String result = null;
348 |
349 | String accountClause = InstalledApp.PACKAGE_NAME + " = ?";
350 |
351 | String[] args = new String[] { mPackageName };
352 |
353 | Cursor cursor = mContentResolver.query(InstalledApp.CONTENT_URI,
354 | PROJECTION_INSTALL_APP, accountClause, args, null);
355 |
356 | if (cursor == null) {
357 | Log.d(TAG, " testBaseInfoView cursor = " + cursor);
358 | }
359 |
360 | if ( cursor != null ) {
361 |
362 | ArrayList ops = new ArrayList();
363 |
364 | if (cursor.getCount() > 0) {
365 | updateInstallAppRecord(ops, false);
366 | } else {
367 | appendInstallAppRecord(ops);
368 | }
369 |
370 | try {
371 | getContentResolver().applyBatch(SuitScreen.AUTHORITY, ops);
372 | } catch (Exception e) {
373 | result = getResources().getString(R.string.data_error);
374 | // Log exception
375 | Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
376 | }
377 | }
378 |
379 | return result;
380 | }
381 |
382 |
383 |
384 | private String handleRemoveAppRecord() {
385 | String result = null;
386 |
387 | String accountClause = InstalledApp.PACKAGE_NAME + " = ?";
388 |
389 | String[] args = new String[] { mPackageName };
390 |
391 | Cursor cursor = mContentResolver.query(InstalledApp.CONTENT_URI,
392 | PROJECTION_INSTALL_APP, accountClause, args, null);
393 |
394 | if (cursor == null) {
395 | Log.d(TAG, " testBaseInfoView cursor = " + cursor);
396 | }
397 |
398 | if ( cursor != null ) {
399 |
400 | ArrayList ops = new ArrayList();
401 |
402 | Log.d(TAG, " handleRemoveAppRecord mPackageName = " + mPackageName + " cursor.getCount() = " +
403 | cursor.getCount() );
404 |
405 | if (cursor.getCount() > 0) {
406 | updateInstallAppRecord(ops, true);
407 | }
408 |
409 | try {
410 | getContentResolver().applyBatch(SuitScreen.AUTHORITY, ops);
411 | } catch (Exception e) {
412 | result = getResources().getString(R.string.data_error);
413 | // Log exception
414 | Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
415 | }
416 | }
417 |
418 | return result;
419 | }
420 |
421 | private void appendInstallAppRecord(ArrayList ops) {
422 | Log.d(TAG, "appendInstallAppRecord mPackageName = " + mPackageName + " mClassName = " +
423 | mClassName + " isActivityStart = " +isActivityStart);
424 | ops.add( ContentProviderOperation.newInsert(InstalledApp.CONTENT_URI)
425 | .withValue(InstalledApp.PACKAGE_NAME, mPackageName)
426 | .withValue(InstalledApp.CLASS_NAME, mClassName)
427 | .withValue(InstalledApp.ACTIVITY_START, isActivityStart == false ? 0 : 1)
428 | .build() );
429 | }
430 |
431 | private void updateInstallAppRecord(ArrayList ops, boolean deleted) {
432 | StringBuilder stringBuilder = new StringBuilder();
433 | stringBuilder.setLength(0);
434 | stringBuilder.append(InstalledApp.PACKAGE_NAME + " = ? ");
435 |
436 | int del = (deleted == false ? 0 : 1);
437 | int start = (isActivityStart == false ? 0 : 1);
438 |
439 | ops.add( ContentProviderOperation.newUpdate(InstalledApp.CONTENT_URI)
440 | .withSelection(stringBuilder.toString(),
441 | new String[] {
442 | mPackageName } )
443 | .withValue(InstalledApp.APP_DELETED, del)
444 | .withValue(InstalledApp.ACTIVITY_START, start)
445 | .build());
446 |
447 |
448 | }
449 |
450 | private String queryAllPackageName() {
451 | String IntegrateString = null;
452 | StringBuilder IntegratePackage = new StringBuilder();
453 | IntegratePackage.setLength(0);
454 |
455 | StringBuilder stringBuilder = new StringBuilder();
456 | stringBuilder.setLength(0);
457 | stringBuilder.append(InstalledApp.APP_DELETED + " = ? " );
458 |
459 |
460 | String[] args = new String[] { String.valueOf( 0 ) };
461 |
462 | Cursor cursor = null;
463 | try {
464 | cursor = mContentResolver.query(InstalledApp.CONTENT_URI,
465 | PROJECTION_INSTALL_APP,
466 | stringBuilder.toString(),
467 | new String[] { String.valueOf(0) },
468 | null);
469 |
470 | if (cursor == null) {
471 | Log.d(TAG, " fillInTotalEnergyInWeek cursor = " + cursor);
472 | }
473 |
474 | cursor.moveToPosition(-1);
475 | Log.d(TAG, "queryAllPackageName cursor.getCount() = " + cursor.getCount() );
476 |
477 | while (cursor.moveToNext() ) {
478 | String packageName = cursor.getString(PACKAGE_NAME_INDEX);
479 | IntegratePackage.append(packageName);
480 | IntegratePackage.append(":");
481 | }
482 |
483 | } finally {
484 | if (cursor != null) {
485 | cursor.close();
486 | }
487 | }
488 |
489 |
490 | Log.d(TAG, "queryAllPackageName IntegratePackage.toString() = " + IntegratePackage);
491 |
492 | if ( IntegratePackage.length() > 0 ) {
493 | IntegrateString = IntegratePackage.substring( 0, IntegratePackage.length() - 1 );
494 | }
495 |
496 | Log.d(TAG, "queryAllPackageName IntegrateString = " + IntegrateString );
497 |
498 | return IntegrateString;
499 |
500 |
501 |
502 | }
503 |
504 |
505 | }
506 |
--------------------------------------------------------------------------------