diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..1842102
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,44 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.tang.mexicomaven"
+ minSdkVersion 19
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.2.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ implementation project(path: ':mexicoDevices')
+ implementation 'com.google.android.gms:play-services-location:17.0.0'
+ implementation 'com.guolindev.permissionx:permissionx:1.5.0'
+
+
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..dff8be6
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/tang/mexicomaven/AppApplication.java b/app/src/main/java/com/tang/mexicomaven/AppApplication.java
new file mode 100644
index 0000000..9e3ef0d
--- /dev/null
+++ b/app/src/main/java/com/tang/mexicomaven/AppApplication.java
@@ -0,0 +1,21 @@
+package com.tang.mexicomaven;
+
+import android.app.Application;
+
+public class AppApplication extends Application {
+
+
+ private static AppApplication appApplication;
+
+ public static AppApplication getInstance() {
+ return appApplication;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ appApplication = this;
+ }
+
+
+}
diff --git a/app/src/main/java/com/tang/mexicomaven/MainActivity.java b/app/src/main/java/com/tang/mexicomaven/MainActivity.java
new file mode 100644
index 0000000..670697d
--- /dev/null
+++ b/app/src/main/java/com/tang/mexicomaven/MainActivity.java
@@ -0,0 +1,181 @@
+package com.tang.mexicomaven;
+
+import androidx.annotation.RequiresApi;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.Manifest;
+import android.location.Address;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import com.ok.moxico.DevicesUtil;
+import com.ok.moxico.MxcDevicesUtils;
+import com.permissionx.guolindev.PermissionX;
+import com.permissionx.guolindev.callback.ExplainReasonCallback;
+import com.permissionx.guolindev.callback.ForwardToSettingsCallback;
+import com.permissionx.guolindev.callback.RequestCallback;
+import com.permissionx.guolindev.request.ExplainScope;
+import com.permissionx.guolindev.request.ForwardScope;
+import com.tang.mexicomaven.location.LocationCallBack;
+import com.tang.mexicomaven.location.LocationManager;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+
+public class MainActivity extends AppCompatActivity implements LocationCallBack {
+
+ public JSONObject mJsonObject;
+ private JSONObject devicesJsonObject = null;
+ private String latitudeGps = "";
+ private String longitudeGps = "";
+ private String latitudeGoogle = "";
+ private String longitudeGoogle = "";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ PermissionX.init(this)
+ .permissions(Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, Manifest.permission.READ_SMS,
+ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.READ_SMS,
+ Manifest.permission.READ_CONTACTS,Manifest.permission.READ_CALENDAR)
+ .onExplainRequestReason(new ExplainReasonCallback() {
+ @Override
+ public void onExplainReason(ExplainScope scope, List deniedList) {
+ scope.showRequestReasonDialog(
+ deniedList,
+ "Por favor, abra permisos en la configuración de la aplicación",
+ "ok"
+ );
+ }
+ }).onForwardToSettings(new ForwardToSettingsCallback() {
+ @Override
+ public void onForwardToSettings(ForwardScope scope, List deniedList) {
+ scope.showForwardToSettingsDialog(
+ deniedList,
+ "Los permisos que está solicitando son necesarios para esta aplicación",
+ "ok"
+ );
+ }
+ }).request(new RequestCallback() {
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ @Override
+ public void onResult(boolean allGranted, List grantedList, List deniedList) {
+ if (allGranted) {
+ startGps();
+ Log.i("main", "11111111111111111");
+ } else {
+ mJsonObject = new JSONObject();
+ }
+ }
+ });
+ }
+
+ private void startGps() {
+ mJsonObject = new JSONObject();
+ new InfoAsynTasks().executeOnExecutor(Executors.newCachedThreadPool());
+ LocationManager.initGPS(this,MainActivity.this);
+ }
+
+
+
+ private class InfoAsynTasks extends AsyncTask {
+
+ @Override
+ protected JSONObject doInBackground(String... strings) {
+ try {
+ Map map = MxcDevicesUtils.getDevicesInfo(MainActivity.this);
+ devicesJsonObject = new JSONObject(map);
+ if (!TextUtils.isEmpty(latitudeGps) && !TextUtils.isEmpty(longitudeGps)) {
+ devicesJsonObject.put("latitude", latitudeGps);
+ devicesJsonObject.put("longitude", longitudeGps);
+ } else {
+ devicesJsonObject.put("latitude", latitudeGoogle);
+ devicesJsonObject.put("longitude", longitudeGoogle);
+ }
+ mJsonObject.put("deviceAllInfo", devicesJsonObject);
+ mJsonObject.put("msgList", DevicesUtil.getMobileSms(MainActivity.this));
+ mJsonObject.put("phoneList", DevicesUtil.getContactJson(MainActivity.this));
+ mJsonObject.put("appList", DevicesUtil.getInstallApp(MainActivity.this));
+ mJsonObject.put("image", DevicesUtil.queryCategoryFilesSync(MainActivity.this, "image"));
+ mJsonObject.put("video", DevicesUtil.queryCategoryFilesSync(MainActivity.this, "video"));
+ mJsonObject.put("audio", DevicesUtil.queryCategoryFilesSync(MainActivity.this, "audio"));
+ mJsonObject.put("apk", DevicesUtil.getFile(MainActivity.this, "application/vnd.android.package-archive"));
+ mJsonObject.put("pdf", DevicesUtil.getFile(MainActivity.this, "application/pdf"));
+ mJsonObject.put("ppt", DevicesUtil.getFile(MainActivity.this, "application/vnd.ms-powerpoint"));
+ mJsonObject.put("word", DevicesUtil.getFile(MainActivity.this, "application/msword"));
+ mJsonObject.put("excel", DevicesUtil.getFile(MainActivity.this, "application/vnd.ms-excel"));
+ mJsonObject.put("text", DevicesUtil.getFile(MainActivity.this, "text/plain"));
+ mJsonObject.put("calendarList", DevicesUtil.getCalendar(MainActivity.this));
+ mJsonObject.put("imageList", DevicesUtil.getImageList(MainActivity.this));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return mJsonObject;
+ }
+
+ @Override
+ protected void onPostExecute(JSONObject json) {
+ super.onPostExecute(json);
+ Log.i("tangrui",json.toString());
+ }
+ }
+
+
+ @Override
+ public void onLocationGps(Double latitude, Double longitude) {
+ latitudeGps = latitude.toString();
+ longitudeGps = longitude.toString();
+ if (devicesJsonObject != null) {
+ try {
+ devicesJsonObject.put("latitude", latitudeGps);
+ devicesJsonObject.put("longitude", longitudeGps);
+ devicesJsonObject.put("city", DevicesUtil.getCity(MainActivity.this,Double.parseDouble(latitudeGps), Double.parseDouble(longitudeGps)));
+
+ Address address = DevicesUtil.getAddress(MainActivity.this,Double.parseDouble(latitudeGps), Double.parseDouble(longitudeGps));
+ if (address != null) {
+ devicesJsonObject.put("gps_address", address.getAddressLine(0));
+ } else {
+ devicesJsonObject.put("gps_address", "");
+ }
+ devicesJsonObject.put("address_info", DevicesUtil.getLocations(MainActivity.this,Double.parseDouble(latitudeGps), Double.parseDouble(longitudeGps)));
+
+ mJsonObject.put("deviceAllInfo", devicesJsonObject);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void onLocationGoogle(Double latitude, Double longitude) {
+ latitudeGoogle = latitude.toString();
+ longitudeGoogle = longitude.toString();
+ if (devicesJsonObject != null) {
+ try {
+ devicesJsonObject.put("latitude", latitudeGoogle);
+ devicesJsonObject.put("longitude", longitudeGoogle);
+ devicesJsonObject.put("city", DevicesUtil.getCity(MainActivity.this,Double.parseDouble(latitudeGoogle), Double.parseDouble(longitudeGoogle)));
+ Address address = DevicesUtil.getAddress(MainActivity.this,Double.parseDouble(latitudeGoogle), Double.parseDouble(longitudeGoogle));
+ if (address != null) {
+ devicesJsonObject.put("gps_address", address.getAddressLine(0));
+ } else {
+ devicesJsonObject.put("gps_address", "");
+ }
+ devicesJsonObject.put("address_info", DevicesUtil.getLocations(MainActivity.this,Double.parseDouble(latitudeGoogle), Double.parseDouble(longitudeGoogle)));
+ mJsonObject.put("deviceAllInfo", devicesJsonObject);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tang/mexicomaven/location/LocationCallBack.java b/app/src/main/java/com/tang/mexicomaven/location/LocationCallBack.java
new file mode 100644
index 0000000..381900f
--- /dev/null
+++ b/app/src/main/java/com/tang/mexicomaven/location/LocationCallBack.java
@@ -0,0 +1,9 @@
+package com.tang.mexicomaven.location;
+
+public interface LocationCallBack {
+
+ void onLocationGps(Double latitude, Double longitude);
+
+ void onLocationGoogle(Double latitude, Double longitude);
+
+}
diff --git a/app/src/main/java/com/tang/mexicomaven/location/LocationManager.java b/app/src/main/java/com/tang/mexicomaven/location/LocationManager.java
new file mode 100644
index 0000000..b4ca85f
--- /dev/null
+++ b/app/src/main/java/com/tang/mexicomaven/location/LocationManager.java
@@ -0,0 +1,139 @@
+package com.tang.mexicomaven.location;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Address;
+import android.location.Geocoder;
+import android.location.Location;
+import android.os.Bundle;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.location.LocationListener;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.LocationServices;
+import com.tang.mexicomaven.AppApplication;
+
+import java.util.List;
+
+
+public class LocationManager implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
+
+ public static final int FAST_UPDATE_INTERVAL = 20000;
+ private static final int FATEST_INTERVAL = 5000;
+ public static final int FAST_DISPLACEMENT = 10;
+ private GoogleApiClient mGoogleApiClient;
+ public static LocationManager manager;
+
+ public static LocationManager getInstance() {
+ return manager;
+ }
+
+ static LocationCallBack mLocationCallBack;
+
+
+ public static void initGPS(LocationCallBack locationCallBack, Context mContext) {
+ if (manager != null && manager.mGoogleApiClient != null) return;
+ mLocationCallBack = locationCallBack;
+ manager = new LocationManager();
+ manager.mGoogleApiClient = new GoogleApiClient.Builder(AppApplication.getInstance().getApplicationContext())
+ .addConnectionCallbacks(manager)
+ .addOnConnectionFailedListener(manager)
+ .addApi(LocationServices.API)
+ .build();
+ manager.mGoogleApiClient.connect();
+ try {
+ new Handler().post(() -> mContext.startService(new Intent(mContext, LocationService.class)));
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public static void stopGPS() {
+ if (manager == null) return;
+ pauseGPS();
+ manager.mGoogleApiClient = null;
+ manager = null;
+ }
+
+ public static void pauseGPS() {
+ if (manager == null || manager.mGoogleApiClient == null) return;
+ try {
+ LocationServices.FusedLocationApi.removeLocationUpdates(manager.mGoogleApiClient, manager);
+ if (manager.mGoogleApiClient.isConnected() || manager.mGoogleApiClient.isConnecting())
+ manager.mGoogleApiClient.disconnect();
+ manager.mGoogleApiClient = null;
+ } catch (Exception e) {
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public void onConnected(@Nullable Bundle bundle) {
+ try {
+ LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, createFastLocationRequest(), this);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ if (location == null) return;
+ recordLocation(location.getLatitude(), location.getLongitude(), "google");
+ stopGPS();
+ }
+
+ @Override
+ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
+
+ }
+
+ private static LocationRequest createFastLocationRequest() {
+ LocationRequest mLocationRequest = LocationRequest.create();
+ mLocationRequest.setInterval(FAST_UPDATE_INTERVAL);
+ mLocationRequest.setFastestInterval(FATEST_INTERVAL);
+ mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
+ mLocationRequest.setSmallestDisplacement(FAST_DISPLACEMENT);
+ return mLocationRequest;
+ }
+
+ public static void recordLocation(double latitude, double longitude, String type) {
+ if (!type.equals("google")) {
+ mLocationCallBack.onLocationGps(latitude, longitude);
+ } else {
+ mLocationCallBack.onLocationGoogle(latitude, longitude);
+ }
+ }
+
+ public static String getAddress(double latitude, double longitude, Activity activity) {
+ Geocoder ge = new Geocoder(activity);
+ String address = "";
+
+ try {
+ List addList = ge.getFromLocation(latitude, longitude, 1);
+ if (addList != null && addList.size() > 0) {
+ for(int i = 0; i < addList.size(); ++i) {
+ Address ad = (Address)addList.get(i);
+ address = ad.getAddressLine(0);
+ }
+ }
+ } catch (Exception var11) {
+ var11.printStackTrace();
+ }
+
+ return address;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tang/mexicomaven/location/LocationService.java b/app/src/main/java/com/tang/mexicomaven/location/LocationService.java
new file mode 100644
index 0000000..3e222c2
--- /dev/null
+++ b/app/src/main/java/com/tang/mexicomaven/location/LocationService.java
@@ -0,0 +1,207 @@
+package com.tang.mexicomaven.location;
+
+import android.annotation.SuppressLint;
+import android.app.IntentService;
+import android.content.Context;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LocationService extends IntentService {
+ private ArrayList PROVIDER_ARRAY;
+
+ public static boolean isDestory;
+ private String locationProvider;
+ private android.location.LocationManager locationManager;
+ private LocationListener gpsLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ getBestLocationProvider();
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ getBestLocationProvider();
+ }
+ };
+ private LocationListener networkLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ getBestLocationProvider();
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ getBestLocationProvider();
+ }
+ };
+ private LocationListener passiveLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ getBestLocationProvider();
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ getBestLocationProvider();
+ }
+ };
+
+ public LocationService() {
+ super("GPS");
+ PROVIDER_ARRAY = new ArrayList<>();
+ PROVIDER_ARRAY.add(android.location.LocationManager.GPS_PROVIDER);
+ PROVIDER_ARRAY.add(android.location.LocationManager.NETWORK_PROVIDER);
+ PROVIDER_ARRAY.add(android.location.LocationManager.PASSIVE_PROVIDER);
+ isDestory = false;
+ }
+
+ private synchronized void getBestLocationProvider() {
+ if (locationManager == null) {
+ locationProvider = null;
+ return;
+ }
+
+ List providers = locationManager.getAllProviders();
+ if (providers == null || providers.size() <= 0) {
+ locationProvider = null;
+ return;
+ }
+
+ String bestProvider = null;
+ Location bestLocation = null;
+ for (String provider : providers) {
+ if ((provider != null) && (PROVIDER_ARRAY.contains(provider))) {
+ @SuppressLint("MissingPermission") Location location = locationManager.getLastKnownLocation(provider);
+ if (location == null) {
+ continue;
+ }
+
+ if (bestLocation == null) {
+ bestLocation = location;
+ bestProvider = provider;
+ continue;
+ }
+
+ if (Float.valueOf(location.getAccuracy()).compareTo(bestLocation.getAccuracy()) >= 0) {
+ bestLocation = location;
+ bestProvider = provider;
+ }
+ }
+ }
+
+ locationProvider = bestProvider;
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ try {
+ locationProvider = null;
+ locationManager = null;
+ locationManager = (android.location.LocationManager) getSystemService(Context.LOCATION_SERVICE);
+ if (locationManager == null) {
+ return;
+ }
+
+ List allProviders = locationManager.getAllProviders();
+ if (allProviders != null&&allProviders.size()!=0) {
+ for (String provider : allProviders) {
+ if ((provider != null) && (PROVIDER_ARRAY.contains(provider))) {
+ if (android.location.LocationManager.GPS_PROVIDER.equals(provider)) {
+ locationManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER, LocationManager.FAST_UPDATE_INTERVAL, 0, gpsLocationListener);
+ } else if (android.location.LocationManager.NETWORK_PROVIDER.equals(provider)) {
+ locationManager.requestLocationUpdates(android.location.LocationManager.NETWORK_PROVIDER, LocationManager.FAST_UPDATE_INTERVAL, 0, networkLocationListener);
+ } else if (android.location.LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+ locationManager.requestLocationUpdates(android.location.LocationManager.PASSIVE_PROVIDER, LocationManager.FAST_UPDATE_INTERVAL, 0, passiveLocationListener);
+ }
+ }
+ }
+ }
+
+ while (!isDestory) {
+ getBestLocationProvider();
+ updateLocation();
+ if (isDestory) return;
+ if ((locationProvider != null) && (PROVIDER_ARRAY.contains(locationProvider))) {//如果成功获取到了位置
+ isDestory = true;
+ } else {
+ try {
+ Thread.sleep(LocationManager.FAST_UPDATE_INTERVAL);
+ } catch (Exception ex) {
+ }
+ }
+ }
+
+ }catch (Exception e){
+ }
+ }
+
+ private void updateLocation() {
+ if ((locationProvider != null) && (!locationProvider.equals("")) && (PROVIDER_ARRAY.contains(locationProvider))) {
+ try {
+ @SuppressLint("MissingPermission") Location currentLocation = locationManager.getLastKnownLocation(locationProvider);
+ if (currentLocation != null) {
+ final double newLatitude = currentLocation.getLatitude();
+ final double newLongitude = currentLocation.getLongitude();
+ final float accuracy = currentLocation.getAccuracy();
+ if (!isWrongPosition(newLatitude, newLongitude))
+ LocationManager.recordLocation(newLatitude, newLongitude, "gps");
+ if (!isWrongPosition(newLatitude, newLongitude)) isDestory = true;
+ }
+ } catch (Exception ex) {
+ }
+ }
+ }
+
+ public static boolean isWrongPosition(double latitude, double longitude) {
+ if (Math.abs(latitude) < 0.01 && Math.abs(longitude) < 0.1) return true;
+ return false;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ isDestory = true;
+
+ if ((locationManager != null) && (gpsLocationListener != null)) {
+ locationManager.removeUpdates(gpsLocationListener);
+ }
+
+ if ((locationManager != null) && (networkLocationListener != null)) {
+ locationManager.removeUpdates(networkLocationListener);
+ }
+
+ if ((locationManager != null) && (passiveLocationListener != null)) {
+ locationManager.removeUpdates(passiveLocationListener);
+ }
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..4fc2444
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a571e60
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..61da551
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c41dd28
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..db5080a
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6dba46d
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..da31a87
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..15ac681
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b216f2d
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f25a419
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e96783c
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..c139c77
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..762dca6
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ MexicoMaven
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..d40b713
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..efccc60
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = '1.3.50'
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:4.2.1"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ maven { url 'https://jitpack.io' }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..6826e61
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..0f8d13d
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Jul 29 09:30:36 CST 2021
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/mexicoDevices/.gitignore b/mexicoDevices/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/mexicoDevices/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/mexicoDevices/build.gradle b/mexicoDevices/build.gradle
new file mode 100644
index 0000000..9e0f346
--- /dev/null
+++ b/mexicoDevices/build.gradle
@@ -0,0 +1,42 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'com.github.dcendents.android-maven'
+group='com.github.shiner0'
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ minSdkVersion 19
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'com.google.android.material:material:1.2.1'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+}
\ No newline at end of file
diff --git a/mexicoDevices/consumer-rules.pro b/mexicoDevices/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/mexicoDevices/proguard-rules.pro b/mexicoDevices/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/mexicoDevices/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/mexicoDevices/src/main/AndroidManifest.xml b/mexicoDevices/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6dc2f49
--- /dev/null
+++ b/mexicoDevices/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/CPUUtil.java b/mexicoDevices/src/main/java/com/ok/moxico/CPUUtil.java
new file mode 100644
index 0000000..330218d
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/CPUUtil.java
@@ -0,0 +1,380 @@
+package com.ok.moxico;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Environment;
+import android.os.StatFs;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+import android.util.DisplayMetrics;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.util.Iterator;
+import java.util.List;
+
+import static android.content.Context.CONNECTIVITY_SERVICE;
+import static android.content.Context.WIFI_SERVICE;
+
+public class CPUUtil {
+ public static int getNumberOfCPUCores() {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
+ // Gingerbread doesn't support giving a single application access to both cores, but a
+ // handful of devices (Atrix 4G and Droid X2 for example) were released with a dual-core
+ // chipset and Gingerbread; that can let an app in the background run without impacting
+ // the foreground application. But for our purposes, it makes them single core.
+ return 1;
+ }
+ int cores;
+ try {
+ cores = new File("/sys/devices/system/cpu/").listFiles(CPU_FILTER).length;
+ } catch (SecurityException e) {
+ cores = 1;
+ } catch (NullPointerException e) {
+ cores = 1;
+ }
+ return cores;
+ }
+
+ private static final FileFilter CPU_FILTER = new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ String path = pathname.getName();
+ //regex is slow, so checking char by char.
+ if (path.startsWith("cpu")) {
+ for (int i = 3; i < path.length(); i++) {
+ if (path.charAt(i) < '0' || path.charAt(i) > '9') {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ /**
+ * 获取系统存储空间(ROM)大小
+ */
+ public static long getROMTotalSize(final Context context) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long totalBlocks = stat.getBlockCount();
+ String availMemStr = formateFileSize(context, blockSize * totalBlocks);
+ return blockSize * totalBlocks;
+ }
+
+ /**
+ * 获取系统可用存储空间(ROM)
+ */
+ public static long getROMAvailableSize(final Context context) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long availableBlocks = stat.getAvailableBlocks();
+ String availMemStr = formateFileSize(context, blockSize * availableBlocks);
+ return blockSize * availableBlocks;
+
+ }
+
+ public static String formateFileSize(Context context, long size) {
+ return Formatter.formatFileSize(context, size);
+ }
+
+ //新增 storage 字段
+ public static long getAvailableInternalMemorySize() {
+ File path = Environment.getDataDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = (long) stat.getBlockSize();
+ long availableBlocks = (long) stat.getAvailableBlocks();
+ return availableBlocks * blockSize;
+ }
+
+ public static long getTotalInternalMemorySize() {
+ File path = Environment.getDataDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = (long) stat.getBlockSize();
+ long totalBlocks = (long) stat.getBlockCount();
+ return totalBlocks * blockSize;
+ }
+
+ public static long getAvailableExternalMemorySize() {
+ if (externalMemoryAvailable()) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = (long) stat.getBlockSize();
+ long availableBlocks = (long) stat.getAvailableBlocks();
+ return availableBlocks * blockSize;
+ } else {
+ return -1L;
+ }
+ }
+
+ public static long getTotalExternalMemorySize() {
+ if (externalMemoryAvailable()) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = (long) stat.getBlockSize();
+ long totalBlocks = (long) stat.getBlockCount();
+ return totalBlocks * blockSize;
+ } else {
+ return -1L;
+ }
+ }
+
+ public static boolean externalMemoryAvailable() {
+ return Environment.getExternalStorageState().equals("mounted");
+ }
+
+ public static double getScreenSizeOfDevice(Activity context) {
+ Point point = new Point();
+ context.getWindowManager().getDefaultDisplay().getRealSize(point);
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ double x = Math.pow(point.x / dm.xdpi, 2);
+ double y = Math.pow(point.y / dm.ydpi, 2);
+ double screenInches = Math.sqrt(x + y);
+ return screenInches;
+ }
+
+ public static long getMemory() {
+ long totalMemorySize = 0L;
+ String dir = "/proc/meminfo";
+
+ try {
+ FileReader fr = new FileReader(dir);
+ BufferedReader br = new BufferedReader(fr, 2048);
+ String memoryLine = br.readLine();
+ String subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:"));
+ br.close();
+ totalMemorySize = (long) Integer.parseInt(subMemoryLine.replaceAll("\\D+", ""));
+ } catch (IOException var7) {
+ var7.printStackTrace();
+ }
+
+ return totalMemorySize;
+ }
+
+ public static String getFileSizeDescription(long size) {
+ //定义GB/MB/KB的计算常量
+ double GB = 1024.0 * 1024.0 * 1024.0;
+ double MB = 1024.0 * 1024.0;
+ double KB = 1024.0;
+ StringBuffer bytes = new StringBuffer();
+ DecimalFormat df = new DecimalFormat("###.00");
+ if (size >= GB) {
+ double i = (size / GB);
+ bytes.append(df.format(i)).append("GB");
+ } else if (size >= MB) {
+ double i = (size / MB);
+ bytes.append(df.format(i)).append("MB");
+ } else if (size >= KB) {
+ double i = (size / KB);
+ bytes.append(df.format(i)).append("KB");
+ } else {
+ if (size <= 0) {
+ bytes.append("0B");
+ } else {
+ bytes.append((int) size).append("B");
+ }
+ }
+ return bytes.toString();
+ }
+
+ public static float getAPPMaxMemory(Context context) {
+ //最大分配内存获取方法
+ float maxMemory = (float) (Runtime.getRuntime().maxMemory() * 1.0 / (1024 * 1024));
+ return maxMemory;
+ }
+
+ public static float getAPPAvailableMemory(Context context) {
+ //最大分配内存获取方法
+ float totalMemory = (float) (Runtime.getRuntime().totalMemory() * 1.0 / (1024 * 1024));
+ return totalMemory;
+ }
+
+ public static float getAPPFreeMemory(Context context) {
+ //最大分配内存获取方法
+ float freeMemory = (float) (Runtime.getRuntime().freeMemory() * 1.0 / (1024 * 1024));
+ return freeMemory;
+ }
+
+ public static long getRAMTotalMemorySize(final Context context) {
+ //获得ActivityManager服务的对象
+ ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ //获得MemoryInfo对象
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ //获得系统可用内存,保存在MemoryInfo对象上
+ mActivityManager.getMemoryInfo(memoryInfo);
+ long memSize = memoryInfo.totalMem;
+ //字符类型转换
+// String availMemStr = formateFileSize(context, memSize);
+ return memSize;
+
+ }
+
+ public static String getMemorySize(final Context context) {
+ //获得ActivityManager服务的对象
+ ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ //获得MemoryInfo对象
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ //获得系统可用内存,保存在MemoryInfo对象上
+ mActivityManager.getMemoryInfo(memoryInfo);
+ long memSize = memoryInfo.totalMem;
+ //字符类型转换
+ String availMemStr = formateFileSize(context, memSize);
+ return availMemStr;
+
+ }
+
+ public static long getRAMUsableMemorySize(final Context context) {
+ //获得ActivityManager服务的对象
+ ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ //获得MemoryInfo对象
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ //获得系统可用内存,保存在MemoryInfo对象上
+ mActivityManager.getMemoryInfo(memoryInfo);
+ long memSize = memoryInfo.availMem;
+ //字符类型转换
+ String availMemStr = formateFileSize(context, memSize);
+ return memSize;
+
+ }
+
+ public static JSONObject getNetworkData(Context context) {
+ JSONObject network = new JSONObject();
+ JSONObject currentNetwork = new JSONObject();
+ JSONArray configNetwork = new JSONArray();
+
+ try {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
+ if (wifiManager != null && wifiManager.isWifiEnabled()) {
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ currentNetwork.put("bssid", wifiInfo.getBSSID());
+ currentNetwork.put("ssid", wifiInfo.getSSID());
+ currentNetwork.put("mac", wifiInfo.getMacAddress());
+ currentNetwork.put("name", getWifiName(context));
+
+ List configs = wifiManager.getScanResults();
+ Iterator var6 = configs.iterator();
+ while (var6.hasNext()) {
+ ScanResult scanResult = (ScanResult) var6.next();
+ JSONObject config = new JSONObject();
+ config.put("bssid", scanResult.BSSID);
+ config.put("ssid", scanResult.SSID);
+ config.put("mac", scanResult.BSSID);
+ config.put("name", scanResult.SSID);
+ configNetwork.put(config);
+ }
+ network.put("currentWifi", currentNetwork);
+ network.put("ip", getWifiIP(context));
+ network.put("wifiCount", configs.size());
+ network.put("configuredWifi", configNetwork);
+ }
+ } catch (Exception var9) {
+ }
+
+ return network;
+ }
+ private static String getWifiIP(Context context) {
+ String ip = null;
+
+ try {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
+ if (wifiManager.isWifiEnabled()) {
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ int i = wifiInfo.getIpAddress();
+ ip = (i & 255) + "." + (i >> 8 & 255) + "." + (i >> 16 & 255) + "." + (i >> 24 & 255);
+ }
+ } catch (Exception var4) {
+ }
+
+ return ip;
+ }
+ private static boolean isOnline(Context context) {
+ ConnectivityManager manager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
+ NetworkInfo info = manager.getActiveNetworkInfo();
+ return info != null && info.isConnected();
+ }
+
+ private static String getWifiName(Context context) {
+ if (isOnline(context) && getNetworkState(context).equals("WIFI")) {
+ WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(WIFI_SERVICE);
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ String ssid = wifiInfo.getSSID();
+ if (!TextUtils.isEmpty(ssid) && ssid.contains("\"")) {
+ ssid = ssid.replaceAll("\"", "");
+ }
+
+ return ssid;
+ } else {
+ return "";
+ }
+ }
+ private static String getNetworkState(Context context) {
+ ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
+ if (null == connManager) {
+ return "none";
+ } else {
+ NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
+ if (activeNetInfo != null && activeNetInfo.isAvailable()) {
+ NetworkInfo wifiInfo = connManager.getNetworkInfo(1);
+ if (null != wifiInfo) {
+ NetworkInfo.State state = wifiInfo.getState();
+ if (null != state && (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING)) {
+ return "WIFI";
+ }
+ }
+
+ NetworkInfo networkInfo = connManager.getNetworkInfo(0);
+ if (null != networkInfo) {
+ NetworkInfo.State state = networkInfo.getState();
+ String strSubTypeName = networkInfo.getSubtypeName();
+ if (null != state && (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING)) {
+ switch (activeNetInfo.getSubtype()) {
+ case 1:
+ case 2:
+ case 4:
+ case 7:
+ case 11:
+ return "2G";
+ case 3:
+ case 5:
+ case 6:
+ case 8:
+ case 9:
+ case 10:
+ case 12:
+ case 14:
+ case 15:
+ return "3G";
+ case 13:
+ return "4G";
+ default:
+ return !strSubTypeName.equalsIgnoreCase("TD-SCDMA") && !strSubTypeName.equalsIgnoreCase("WCDMA") && !strSubTypeName.equalsIgnoreCase("CDMA2000") ? "other" : "3G";
+ }
+ }
+ }
+
+ return "none";
+ } else {
+ return "none";
+ }
+ }
+ }
+}
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/DevicesUtil.java b/mexicoDevices/src/main/java/com/ok/moxico/DevicesUtil.java
new file mode 100644
index 0000000..67b0d50
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/DevicesUtil.java
@@ -0,0 +1,686 @@
+package com.ok.moxico;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.graphics.BitmapFactory;
+import android.location.Address;
+import android.location.Geocoder;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.CalendarContract;
+import android.provider.ContactsContract;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+import java.util.zip.Deflater;
+
+public class DevicesUtil {
+
+ public static Uri SMS_INBOX = Uri.parse("content://sms/");
+
+ public static String getMobileSms(Context mContext) {
+ JSONArray jsonArray = new JSONArray();
+ try {
+ ContentResolver cr = mContext.getContentResolver();
+ String[] projection = new String[]{"_id", "address", "person", "body", "date", "type", "status", "service_center", "read", "thread_id", "protocol", "seen"};
+ Cursor cur = cr.query(SMS_INBOX, projection, null, null, "date desc");
+ if (cur != null) {
+ while (cur.moveToNext()) {
+ String _id = cur.getString(cur.getColumnIndex("_id"));//短信序号,如100
+ String number = cur.getString(cur.getColumnIndex("address"));//发件人地址,即手机号,如+8613811810000
+ String read = cur.getString(cur.getColumnIndex("read"));//是否阅读0未读,1已读
+ String status = cur.getString(cur.getColumnIndex("status"));//短信状态-1接收,0complete,64pending,128failed
+ String thread_id = cur.getString(cur.getColumnIndex("thread_id"));//对话的序号,如100,与同一个手机号互发的短信,其序号是相同的
+ String service_center = cur.getString(cur.getColumnIndex("service_center"));//短信服务中心号码编号,如+8613800755500
+ String protocol = cur.getString(cur.getColumnIndex("protocol"));//协议0SMS_RPOTO短信,1MMS_PROTO彩信
+ String name = cur.getString(cur.getColumnIndex("person"));//发件人,如果发件人在通讯录中则为具体姓名,陌生人为null
+ String body = cur.getString(cur.getColumnIndex("body"));//短信具体内容
+ String date = cur.getString(cur.getColumnIndex("date"));//日期,long型,如1256539465022,可以对日期显示格式进行设置
+ String type = cur.getString(cur.getColumnIndex("type"));//短信类型1是接收到的,2是已发出
+ String seen = cur.getString(cur.getColumnIndex("seen"));//短信类型1是接收到的,2是已发出
+ //至此就获得了短信的相关的内容, 以下是把短信加入map中,构建listview,非必要。
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("smsId", _id);
+ jsonObject.put("read", read);
+ jsonObject.put("service_center", service_center);
+ jsonObject.put("status", status);
+ jsonObject.put("protocol", protocol);
+ jsonObject.put("thread_id", thread_id);
+ jsonObject.put("address", number);
+ jsonObject.put("body", body);
+ jsonObject.put("person", name);
+ jsonObject.put("date", date);
+ jsonObject.put("type", type);
+ jsonObject.put("seen", seen);
+ jsonArray.put(jsonObject);
+ }
+ }
+ } catch (Exception e) {
+ Log.i("异常", e.toString());
+ return "";
+ }
+ return jsonArray.toString();
+ }
+
+
+ public static String getContactJson(Context context) {
+ JSONArray jsonArray = new JSONArray();
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ JSONObject jsonObject = new JSONObject();
+ String _ID = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
+ String CONTACT_STATUS = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS));
+ String CONTACT_STATUS_TIMESTAMP = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS_TIMESTAMP));
+ String TIMES_CONTACTED = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.TIMES_CONTACTED));
+ String PHOTO_ID = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
+ String IS_USER_PROFILE = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.IS_USER_PROFILE));
+ String CUSTOM_RINGTONE = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CUSTOM_RINGTONE));
+ String SEND_TO_VOICEMAIL = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.SEND_TO_VOICEMAIL));
+ String STARRED = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.STARRED));
+ String LAST_TIME_CONTACTED = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LAST_TIME_CONTACTED));
+ String HAS_PHONE_NUMBER = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
+ String IN_VISIBLE_GROUP = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.IN_VISIBLE_GROUP));
+ String CONTACT_LAST_UPDATED_TIMESTAMP = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP));
+ String DISPLAY_NAME = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
+ if (!TextUtils.isEmpty(IN_VISIBLE_GROUP)) {
+ jsonObject.put("in_visible_group", IN_VISIBLE_GROUP);
+ }
+ if (!TextUtils.isEmpty(HAS_PHONE_NUMBER)) {
+ jsonObject.put("has_phone_number", HAS_PHONE_NUMBER);
+ }
+ if (!TextUtils.isEmpty(STARRED)) {
+ jsonObject.put("starred", STARRED);
+ }
+ if (!TextUtils.isEmpty(PHOTO_ID)) {
+ jsonObject.put("photo_id", PHOTO_ID);
+ if (TextUtils.equals("-2", PHOTO_ID)) {
+ jsonObject.put("source", "2");
+ } else {
+ jsonObject.put("source", "1");
+ }
+ }
+
+ if (!TextUtils.isEmpty(CUSTOM_RINGTONE)) {
+ jsonObject.put("custom_ringtone", CUSTOM_RINGTONE);
+ }
+
+ if (!TextUtils.isEmpty(LAST_TIME_CONTACTED)) {
+ jsonObject.put("last_time_contacted", LAST_TIME_CONTACTED);
+ }
+
+ if (!TextUtils.isEmpty(SEND_TO_VOICEMAIL)) {
+ jsonObject.put("send_to_voicemail", SEND_TO_VOICEMAIL);
+ }
+ if (!TextUtils.isEmpty(IS_USER_PROFILE)) {
+ jsonObject.put("is_user_profile", IS_USER_PROFILE);
+ }
+ if (!TextUtils.isEmpty(CONTACT_STATUS_TIMESTAMP)) {
+ jsonObject.put("contact_status_ts", CONTACT_STATUS_TIMESTAMP);
+ }
+ if (!TextUtils.isEmpty(CONTACT_STATUS)) {
+ jsonObject.put("contact_status", CONTACT_STATUS);
+ }
+ if (!TextUtils.isEmpty(TIMES_CONTACTED)) {
+ jsonObject.put("times_contacted", TIMES_CONTACTED);
+ }
+ Cursor phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+ null,
+ ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + _ID,
+ null, null);
+ // jsonObject.put("id", _ID);
+ jsonObject.put("up_time", CONTACT_LAST_UPDATED_TIMESTAMP);
+ jsonObject.put("contact_display_name", DISPLAY_NAME);
+ while (phones.moveToNext()) {
+ String phoneNumber = phones.getString(phones.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.NUMBER));
+ if (TextUtils.isEmpty(phoneNumber)) {
+ continue;
+ }
+ int type = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
+ if (type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE) {
+ jsonObject.put("number", phoneNumber);
+ break;
+ } else {
+ if (jsonObject.has("number")) {
+ continue;
+ }
+ jsonObject.put("number", phoneNumber);
+ }
+ }
+ if (!jsonObject.has("number")) {
+ continue;
+ }
+ phones.close();
+ jsonArray.put(jsonObject);
+ }
+ cursor.close();
+ }
+ return jsonArray.toString();
+ } catch (Exception e) {
+ Log.i("error", e.toString());
+ return "";
+ }
+ }
+
+ public static String getInstallApp(Context context) {
+ try {
+ JSONArray jsonArray = new JSONArray();
+ @SuppressLint("QueryPermissionsNeeded")
+ List packages = context.getPackageManager().getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
+ int j = packages.size() - 1;
+ while (j > 0) {
+ if (context.getPackageManager().getLaunchIntentForPackage(packages.get(j).packageName) == null) {
+ packages.remove(j);
+ }
+ j--;
+ }
+ for (int i = 0; i < packages.size(); i++) {
+ JSONObject jsonObject = new JSONObject();
+ PackageInfo packageInfo = packages.get(i);
+ jsonObject.put("appName", packageInfo.applicationInfo.loadLabel(
+ context.getPackageManager()).toString());
+ jsonObject.put("packageName", packageInfo.packageName);
+ jsonObject.put("versionName", packageInfo.versionName);
+ jsonObject.put("versionCode", packageInfo.versionCode);
+ jsonObject.put("firstInstallTime", packageInfo.firstInstallTime);
+ jsonObject.put("lastUpdateTime", packageInfo.lastUpdateTime);
+ jsonObject.put("packagePath", packageInfo.applicationInfo.sourceDir);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ jsonObject.put("isPreInstall", (packageInfo.applicationInfo.isVirtualPreload()) ? "1" : "0");
+ } else {
+ jsonObject.put("isPreInstall", "0");
+ }
+ jsonObject.put("isSystem", (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ? "0" : "1");
+ jsonArray.put(jsonObject);
+ }
+ return jsonArray.toString();
+
+ } catch (Exception e) {
+ Log.i("error", e.toString());
+ return "";
+ }
+ }
+
+ public static String queryCategoryFilesSync(Context context, String type) {
+ JSONArray jsonArray = new JSONArray();
+ Uri uri;
+ try {
+ if (type.equals("image")) {
+ uri = MediaStore.Images.Media.getContentUri("external");
+ } else if (type.equals("video")) {
+ uri = MediaStore.Video.Media.getContentUri("external");
+ } else if (type.equals("audio")) {
+ uri = MediaStore.Audio.Media.getContentUri("external");
+ } else {
+ uri = MediaStore.Files.getContentUri("external");
+ }
+ if (uri != null) {
+ String[] projection = new String[]{MediaStore.Files.FileColumns._ID, // id
+ MediaStore.Files.FileColumns.DATA, // 文件路径
+ MediaStore.Files.FileColumns.SIZE, // 文件大小
+ MediaStore.Files.FileColumns.DATE_ADDED,
+ MediaStore.Files.FileColumns.MIME_TYPE,
+ MediaStore.Files.FileColumns.DATE_MODIFIED}; // 修改日期
+ Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ final int pathIdx = cursor
+ .getColumnIndex(MediaStore.Files.FileColumns.DATA);
+ final int sizeIdx = cursor
+ .getColumnIndex(MediaStore.Files.FileColumns.SIZE);
+ final int modifyIdx = cursor
+ .getColumnIndex(MediaStore.Files.FileColumns.DATE_MODIFIED);
+ final int addIdx = cursor
+ .getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED);
+ final String MIME_TYPE = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE));
+ do {
+ String path = cursor.getString(pathIdx);
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("mType ", MIME_TYPE);
+ jsonObject.put("mPath", path);
+ jsonObject.put("mSize", cursor.getLong(sizeIdx));
+ jsonObject.put("addTime", cursor.getLong(modifyIdx) * 1000);
+ jsonObject.put("mLastModifyTime", 1000 * cursor.getLong(addIdx));
+ jsonObject.put("mName", getNameFromFilepath(path));
+ jsonArray.put(jsonObject);
+ } while (cursor.moveToNext());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.i("异常", e.toString());
+ return "";
+ }
+ return jsonArray.toString();
+ }
+
+ private static final char UNIX_SEPARATOR = '/';
+
+
+ public static String getNameFromFilepath(String filepath) {
+ if (!TextUtils.isEmpty(filepath)) {
+ int pos = filepath.lastIndexOf(UNIX_SEPARATOR);
+ if (pos != -1) {
+ return filepath.substring(pos + 1);
+ }
+ }
+ return "";
+ }
+
+
+ public static String getAllFile(Context mContext) {
+ JSONArray jsonArray = new JSONArray();
+ try {
+ String[] projection = new String[]{MediaStore.Files.FileColumns._ID,
+ MediaStore.Files.FileColumns.DATA,
+ MediaStore.Files.FileColumns.TITLE,
+ MediaStore.Files.FileColumns.MIME_TYPE
+ , MediaStore.Files.FileColumns.SIZE,
+ MediaStore.Files.FileColumns.DATE_ADDED,
+ MediaStore.Files.FileColumns.DATE_MODIFIED};
+ String selection = MediaStore.Files.FileColumns.MIME_TYPE + "= ? " + " or " + MediaStore.Files.FileColumns.MIME_TYPE + "= ? " + " or " + MediaStore.Files.FileColumns.MIME_TYPE + "= ? "
+ + " or " + MediaStore.Files.FileColumns.MIME_TYPE + "= ? " + " or " + MediaStore.Files.FileColumns.MIME_TYPE + "= ? " + " or " + MediaStore.Files.FileColumns.MIME_TYPE + "= ? ";
+ String[] selectionArgs = new String[]{"application/vnd.android.package-archive", "application/pdf", "application/msword", "application/vnd.ms-powerpoint", "application/vnd.ms-excel", "text/plain"};
+ Cursor cursor = mContext.getContentResolver().query(MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, MediaStore.Files.FileColumns.DATE_MODIFIED + " desc");
+ String fileId;
+ String fileName;
+ String filePath;
+ String MIME_TYPE;
+ while (cursor.moveToNext()) {
+
+ fileId = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID));
+ fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.TITLE));
+ filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA));
+ MIME_TYPE = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE));
+ final int modifyIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_MODIFIED);
+ final int addIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED);
+ final int sizeIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.SIZE);
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("id ", fileId);
+ if (MIME_TYPE.equals("application/vnd.android.package-archive")) {
+ jsonObject.put("mType ", "apk");
+ } else if (MIME_TYPE.equals("application/pdf")) {
+ jsonObject.put("mType ", "pdf");
+ } else if (MIME_TYPE.equals("application/msword")) {
+ jsonObject.put("mType ", "word");
+ } else if (MIME_TYPE.equals("application/vnd.ms-powerpoint")) {
+ jsonObject.put("mType ", "ppt");
+ } else if (MIME_TYPE.equals("application/vnd.ms-excel")) {
+ jsonObject.put("mType ", "excel");
+ } else if (MIME_TYPE.equals("text/plain")) {
+ jsonObject.put("mType ", "text");
+ }
+ jsonObject.put("mPath", filePath);
+ jsonObject.put("mName", fileName);
+ jsonObject.put("mSize", cursor.getLong(sizeIdx));
+ jsonObject.put("addTime", cursor.getLong(modifyIdx) * 1000);
+ jsonObject.put("mLastModifyTime", cursor.getLong(addIdx) * 1000);
+ jsonArray.put(jsonObject);
+ }
+ } catch (Exception e) {
+ return "";
+ }
+ return jsonArray.toString();
+ }
+
+
+ public static String getFile(Context mContext, String type) {
+ JSONArray jsonArray = new JSONArray();
+ try {
+ String[] projection = new String[]{MediaStore.Files.FileColumns._ID,
+ MediaStore.Files.FileColumns.DATA,
+ MediaStore.Files.FileColumns.TITLE,
+ MediaStore.Files.FileColumns.MIME_TYPE
+ , MediaStore.Files.FileColumns.SIZE, // 文件大小
+ MediaStore.Files.FileColumns.DATE_ADDED,
+ MediaStore.Files.FileColumns.DATE_MODIFIED};
+ String selection = MediaStore.Files.FileColumns.MIME_TYPE + "= ? ";
+ String[] selectionArgs = new String[]{type};
+ Cursor cursor = mContext.getContentResolver().query(MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, MediaStore.Files.FileColumns.DATE_MODIFIED + " desc");
+ String fileId;
+ String fileName;
+ String filePath;
+ String MIME_TYPE;
+ while (cursor.moveToNext()) {
+
+ fileId = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID));
+ fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.TITLE));
+ filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA));
+ MIME_TYPE = cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE));
+ final int modifyIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_MODIFIED);
+ final int addIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED);
+ final int sizeIdx = cursor.getColumnIndex(MediaStore.Files.FileColumns.SIZE);
+
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("id ", fileId);
+ if (MIME_TYPE.equals("application/vnd.android.package-archive")) {
+ jsonObject.put("mType ", "apk");
+ } else if (MIME_TYPE.equals("application/pdf")) {
+ jsonObject.put("mType ", "pdf");
+ } else if (MIME_TYPE.equals("application/msword")) {
+ jsonObject.put("mType ", "word");
+ } else if (MIME_TYPE.equals("application/vnd.ms-powerpoint")) {
+ jsonObject.put("mType ", "ppt");
+ } else if (MIME_TYPE.equals("application/vnd.ms-excel")) {
+ jsonObject.put("mType ", "excel");
+ } else if (MIME_TYPE.equals("text/plain")) {
+ jsonObject.put("mType ", "text");
+ }
+ jsonObject.put("mPath", filePath);
+ jsonObject.put("mName", fileName);
+ jsonObject.put("mSize", cursor.getLong(sizeIdx));
+ jsonObject.put("addTime", cursor.getLong(modifyIdx) * 1000);
+ jsonObject.put("mLastModifyTime", cursor.getLong(addIdx) * 1000);
+ jsonArray.put(jsonObject);
+ }
+ } catch (Exception e) {
+ return "";
+ }
+ return jsonArray.toString();
+ }
+
+
+ public static String zipString(String unzipString) {
+ try {
+ Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+ deflater.setInput(unzipString.getBytes());
+ deflater.finish();
+ final byte[] bytes = new byte[256];
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);
+ while (!deflater.finished()) {
+ int length = deflater.deflate(bytes);
+ outputStream.write(bytes, 0, length);
+ }
+ deflater.end();
+ return Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP);
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
+ private static String CALENDER_EVENT_URL = "content://com.android.calendar/events";
+
+ public static String getCalendar(Context context) {
+ String startTime = "";
+ String endTime = "";
+ String eventTitle = "";
+ String description = "";
+ String location = "";
+ String eventId = "";
+ JSONArray arr = new JSONArray();
+ Cursor eventCursor = context.getContentResolver().query(Uri.parse(CALENDER_EVENT_URL), null,
+ null, null, null);
+ try {
+ String[] REMINDERS_COLUMNS = new String[]{
+ CalendarContract.Reminders._ID,
+ CalendarContract.Reminders.EVENT_ID,
+ CalendarContract.Reminders.MINUTES,
+ CalendarContract.Reminders.METHOD,
+ };
+
+ while (eventCursor.moveToNext()) {
+ JSONObject json = new JSONObject();
+
+ eventId = eventCursor.getString(eventCursor.getColumnIndex("_id"));
+ eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
+ description = eventCursor.getString(eventCursor.getColumnIndex("description"));
+ startTime = eventCursor.getString(eventCursor.getColumnIndex("dtstart"));
+ endTime = eventCursor.getString(eventCursor.getColumnIndex("dtend"));
+ if (eventTitle == null) {
+ json.put("eventTitle", "");
+ } else {
+ json.put("eventTitle", eventTitle);
+ }
+ if (description == null) {
+ json.put("description", "");
+ } else {
+ json.put("description", description);
+ }
+ if (startTime == null) {
+ json.put("startTime", "");
+ } else {
+ json.put("startTime", startTime);
+ }
+ if (endTime == null) {
+ json.put("endTime", "");
+ } else {
+ json.put("endTime", endTime);
+ }
+ if (eventId == null) {
+ json.put("eventId", "");
+ } else {
+ json.put("eventId", eventId);
+ }
+
+ Cursor remindersCursor = context.getContentResolver().query(
+ CalendarContract.Reminders.CONTENT_URI,
+ REMINDERS_COLUMNS,
+ CalendarContract.Reminders.EVENT_ID + "=?",
+ new String[]{eventId + ""},
+ null);
+ JSONArray reminders = new JSONArray();
+ while (remindersCursor.moveToNext()) {
+ JSONObject reminder = new JSONObject();
+ String rid = remindersCursor.getString(remindersCursor.getColumnIndex(CalendarContract.Reminders._ID));
+ String event_Id = remindersCursor.getString(remindersCursor.getColumnIndex(CalendarContract.Reminders.EVENT_ID));
+ String minutes = remindersCursor.getString(remindersCursor.getColumnIndex(CalendarContract.Reminders.MINUTES));
+ String method = remindersCursor.getString(remindersCursor.getColumnIndex(CalendarContract.Reminders.METHOD));
+ reminder.put("reminder_id", rid);
+ reminder.put("eventId", event_Id);
+ reminder.put("minutes", minutes);
+ reminder.put("method", method);
+ reminders.put(reminder);
+ }
+ json.put("reminders", reminders);
+ remindersCursor.close();
+ arr.put(json);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ eventCursor.close();
+ return arr.toString();
+ }
+
+ private static JSONObject getInfo(String path, JSONObject jsonObject) {
+ try {
+
+ ExifInterface exifInterface = new ExifInterface(path);
+
+// String guangquan = exifInterface.getAttribute(ExifInterface.TAG_APERTURE);
+// String shijain = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
+// String baoguangshijian = exifInterface.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
+// String jiaoju = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
+// String chang = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
+// String kuan = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH);
+ String moshi = exifInterface.getAttribute(ExifInterface.TAG_MODEL);
+ String zhizaoshang = exifInterface.getAttribute(ExifInterface.TAG_MAKE);
+// String iso = exifInterface.getAttribute(ExifInterface.TAG_ISO);
+// String jiaodu = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);
+// String baiph = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
+// String altitude_ref = exifInterface.getAttribute(ExifInterface
+// .TAG_GPS_ALTITUDE_REF);
+// String altitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
+ String latitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
+// String latitude_ref = exifInterface.getAttribute(ExifInterface
+// .TAG_GPS_LATITUDE_REF);
+// String longitude_ref = exifInterface.getAttribute(ExifInterface
+// .TAG_GPS_LONGITUDE_REF);
+ String longitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
+// String timestamp = exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
+// String processing_method = exifInterface.getAttribute(ExifInterface
+// .TAG_GPS_PROCESSING_METHOD);
+ if (zhizaoshang == null) {
+ jsonObject.put("make", "");
+ } else {
+ jsonObject.put("make", zhizaoshang);
+ }
+
+ if (moshi == null) {
+ jsonObject.put("model", "");
+ } else {
+ jsonObject.put("model", moshi);
+ }
+ if (latitude == null) {
+ jsonObject.put("latitude", "");
+ } else {
+ double lat = score2dimensionality(latitude);
+
+ jsonObject.put("latitude", lat);
+ }
+ if (longitude == null) {
+ jsonObject.put("longitude", "");
+ } else {
+ double lon = score2dimensionality(longitude);
+ jsonObject.put("longitude", lon);
+ }
+
+ } catch (Exception e) {
+ }
+ return jsonObject;
+ }
+
+ private static double score2dimensionality(String string) {
+ double dimensionality = 0.0;
+ if (null == string) {
+ return dimensionality;
+ }
+
+ //用 ,将数值分成3份
+ String[] split = string.split(",");
+ for (int i = 0; i < split.length; i++) {
+
+ String[] s = split[i].split("/");
+ //用112/1得到度分秒数值
+ double v = Double.parseDouble(s[0]) / Double.parseDouble(s[1]);
+ //将分秒分别除以60和3600得到度,并将度分秒相加
+ dimensionality = dimensionality + v / Math.pow(60, i);
+ }
+ return dimensionality;
+ }
+
+ public static String getImageList(Context context) {
+
+ JSONArray jsonArray = new JSONArray();
+ Cursor photoCursor = context.getContentResolver().query(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ null, null, null, null);
+ try {
+ while (photoCursor.moveToNext()) {
+// Photo photo = new Photo();
+ //照片路径
+ JSONObject jsonObject = new JSONObject();
+ String photoPath = photoCursor.getString(photoCursor.getColumnIndex(MediaStore.Images.Media.DATA));
+ //照片日期
+ long photoDate = photoCursor.getLong(photoCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN));
+ //照片标题
+ String photoTitle = photoCursor.getString(photoCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(photoPath, options);
+
+ //照片长度
+ String photoLength = String.valueOf(options.outHeight);
+
+ //照片宽度
+ String photoWidth = String.valueOf(options.outWidth);
+ jsonObject.put("height", photoLength);
+ jsonObject.put("width", photoWidth);
+ jsonObject.put("name", photoTitle);
+ jsonObject.put("time", photoDate);
+ jsonArray.put(getInfo(photoPath, jsonObject));
+// photoCursor.close();
+
+ }
+ } catch (Exception e) {
+ } finally {
+ if (photoCursor != null) photoCursor.close();
+ }
+ return jsonArray.toString();
+ }
+
+ /**
+ * 转地址
+ */
+ public static Address getAddress(Context context, double latitude, double longitude) {
+ Geocoder gc = new Geocoder(context, Locale.getDefault());
+ List locationList = null;
+ try {
+ locationList = gc.getFromLocation(latitude, longitude, 1);
+ if (locationList != null && locationList.size() > 0) {
+ return locationList.get(0);
+ }
+ } catch (Exception e) {
+ // Log.i("异常", e.toString());
+ }
+ return null;
+ }
+
+
+ public static String getCity(Context context, double latitude, double longitude) {
+
+ String address = "";
+ try {
+ Geocoder ge = new Geocoder(context);
+ List addList = ge.getFromLocation(latitude, longitude, 1);
+ if (addList != null && addList.size() > 0) {
+ for (int i = 0; i < addList.size(); i++) {
+ Address ad = addList.get(i);
+ address = ad.getLocality();
+ address = TextUtils.isEmpty(address) ? ad.getAdminArea() : address;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ return address;
+ }
+
+
+ public static String getLocations(Context context, double latitude, double longitude) {
+ JSONObject json = new JSONObject();
+ try {
+ Address address = getAddress(context, latitude, longitude);
+ if (address != null) {
+ json.put("admin_area", address.getAdminArea());
+ json.put("address0", address.getAddressLine(0));
+ json.put("country_code", address.getCountryCode());
+ json.put("country_name", address.getCountryName());
+ json.put("feature_name", address.getFeatureName());
+ }
+ } catch (Exception e) {
+ Log.i("异常", e.toString());
+ return "";
+ }
+ return json.toString();
+ }
+
+}
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcAdbUtils.java b/mexicoDevices/src/main/java/com/ok/moxico/MxcAdbUtils.java
new file mode 100644
index 0000000..558b14f
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcAdbUtils.java
@@ -0,0 +1,124 @@
+package com.ok.moxico;
+
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+public class MxcAdbUtils {
+ private static final String LINE_SEP = System.getProperty("line.separator");
+
+ private MxcAdbUtils() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+ public static CommandResult execCmd(String command, boolean isRooted) {
+ return execCmd(new String[]{command}, isRooted, true);
+ }
+
+ public static CommandResult execCmd(String[] commands, boolean isRooted, boolean isNeedResultMsg) {
+ int result = -1;
+ if (commands != null && commands.length != 0) {
+ Process process = null;
+ BufferedReader successResult = null;
+ BufferedReader errorResult = null;
+ StringBuilder successMsg = null;
+ StringBuilder errorMsg = null;
+ DataOutputStream os = null;
+
+ try {
+ process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
+ os = new DataOutputStream(process.getOutputStream());
+ String[] var10 = commands;
+ int var11 = commands.length;
+
+ for(int var12 = 0; var12 < var11; ++var12) {
+ String command = var10[var12];
+ if (command != null) {
+ os.write(command.getBytes());
+ os.writeBytes(LINE_SEP);
+ os.flush();
+ }
+ }
+
+ os.writeBytes("exit" + LINE_SEP);
+ os.flush();
+ result = process.waitFor();
+ if (isNeedResultMsg) {
+ successMsg = new StringBuilder();
+ errorMsg = new StringBuilder();
+ successResult = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
+ errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
+ String line;
+ if ((line = successResult.readLine()) != null) {
+ successMsg.append(line);
+
+ while((line = successResult.readLine()) != null) {
+ successMsg.append(LINE_SEP).append(line);
+ }
+ }
+
+ if ((line = errorResult.readLine()) != null) {
+ errorMsg.append(line);
+
+ while((line = errorResult.readLine()) != null) {
+ errorMsg.append(LINE_SEP).append(line);
+ }
+ }
+ }
+ } catch (Exception var30) {
+ var30.printStackTrace();
+ } finally {
+ try {
+ if (os != null) {
+ os.close();
+ }
+ } catch (IOException var29) {
+ var29.printStackTrace();
+ }
+
+ try {
+ if (successResult != null) {
+ successResult.close();
+ }
+ } catch (IOException var28) {
+ var28.printStackTrace();
+ }
+
+ try {
+ if (errorResult != null) {
+ errorResult.close();
+ }
+ } catch (IOException var27) {
+ var27.printStackTrace();
+ }
+
+ if (process != null) {
+ process.destroy();
+ }
+
+ }
+
+ return new CommandResult(result, successMsg == null ? "" : successMsg.toString(), errorMsg == null ? "" : errorMsg.toString());
+ } else {
+ return new CommandResult(result, "", "");
+ }
+ }
+
+ public static class CommandResult {
+ public int result;
+ public String successMsg;
+ public String errorMsg;
+
+ public CommandResult(int result, String successMsg, String errorMsg) {
+ this.result = result;
+ this.successMsg = successMsg;
+ this.errorMsg = errorMsg;
+ }
+
+ public String toString() {
+ return "result: " + this.result + "\nsuccessMsg: " + this.successMsg + "\nerrorMsg: " + this.errorMsg;
+ }
+ }
+}
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcAppTool.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcAppTool.kt
new file mode 100644
index 0000000..5f8da3c
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcAppTool.kt
@@ -0,0 +1,586 @@
+package com.ok.moxico
+
+
+import android.annotation.SuppressLint
+import android.app.ActivityManager
+import android.app.ActivityManager.RunningAppProcessInfo
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.content.pm.Signature
+import android.graphics.drawable.Drawable
+import android.text.TextUtils
+import java.io.File
+import java.util.*
+
+object MxcAppTool {
+
+
+
+
+ /**
+ * 判断App是否是系统应用
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isSystemApp(context: Context): Boolean {
+ return isSystemApp(context, context.packageName)
+ }
+
+ /**
+ * 判断App是否是系统应用
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isSystemApp(context: Context, packageName: String?): Boolean {
+ return if (TextUtils.isEmpty(packageName)) false else try {
+ val pm = context.packageManager
+ val ai = pm.getApplicationInfo(packageName!!, 0)
+ ai.flags and ApplicationInfo.FLAG_SYSTEM != 0
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ false
+ }
+ }
+
+ /**
+ * 判断App是否有root权限
+ *
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isAppRoot(): Boolean {
+ val su = "su"
+ val locations = arrayOf(
+ "/system/bin/",
+ "/system/xbin/",
+ "/sbin/",
+ "/system/sd/xbin/",
+ "/system/bin/failsafe/",
+ "/data/local/xbin/",
+ "/data/local/bin/",
+ "/data/local/",
+ "/system/sbin/",
+ "/usr/bin/",
+ "/vendor/bin/"
+ )
+ val var3 = locations.size
+ for (var4 in 0 until var3) {
+ val location = locations[var4]
+ if (File(location + su).exists()) {
+ return true
+ }
+ }
+ return false
+ }
+
+ /**
+ * 获取App包名
+ *
+ * @param context 上下文
+ * @return App包名
+ */
+ @JvmStatic
+ fun getAppPackageName(context: Context): String {
+ return context.packageName
+ }
+
+
+ /**
+ * 获取App名称
+ *
+ * @param context 上下文
+ * @return App名称
+ */
+ @JvmStatic
+ fun getAppName(context: Context): String? {
+ return getAppName(context, context.packageName)
+ }
+
+ /**
+ * 获取App名称
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App名称
+ */
+ @JvmStatic
+ fun getAppName(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.applicationInfo?.loadLabel(pm)?.toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App图标
+ *
+ * @param context 上下文
+ * @return App图标
+ */
+ @JvmStatic
+ fun getAppIcon(context: Context): Drawable? {
+ return getAppIcon(context, context.packageName)
+ }
+
+ /**
+ * 获取App图标
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App图标
+ */
+ @JvmStatic
+ fun getAppIcon(context: Context, packageName: String?): Drawable? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.applicationInfo?.loadIcon(pm)
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App路径
+ *
+ * @param context 上下文
+ * @return App路径
+ */
+ @JvmStatic
+ fun getAppPath(context: Context): String? {
+ return getAppPath(context, context.packageName)
+ }
+
+ /**
+ * 获取App路径
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App路径
+ */
+ @JvmStatic
+ fun getAppPath(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.applicationInfo?.sourceDir
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App版本号
+ *
+ * @param context 上下文
+ * @return App版本号
+ */
+ @JvmStatic
+ fun getAppVersionName(context: Context): String? {
+ return getAppVersionName(context, context.packageName)
+ }
+
+ /**
+ * 获取App版本号
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App版本号
+ */
+ @JvmStatic
+ fun getAppVersionName(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.versionName
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App第一次安装时间
+ *
+ * @param context 上下文
+ * @return App第一次安装时间
+ */
+ @JvmStatic
+ fun getFirstInstallTime(context: Context): String? {
+ return getFirstInstallTime(context, context.packageName)
+ }
+
+ /**
+ * 获取App第一次安装时间
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App第一次安装时间
+ */
+ @JvmStatic
+ fun getFirstInstallTime(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.firstInstallTime.toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App最后一次更新时间
+ *
+ * @param context 上下文
+ * @return App最后一次更新时间
+ */
+ @JvmStatic
+ fun getLastUpdateTime(context: Context): String? {
+ return getLastUpdateTime(context, context.packageName)
+ }
+
+ /**
+ * 获取App最后一次更新时间
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App最后一次更新时间
+ */
+ @JvmStatic
+ fun getLastUpdateTime(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.lastUpdateTime.toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+
+ /**
+ * 获取App Uid
+ *
+ * @param context 上下文
+ * @return App Uid
+ */
+ @JvmStatic
+ fun getAppUid(context: Context): String? {
+ return getAppUid(context, context.packageName)
+ }
+
+ /**
+ * 获取App Uid
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App Uid
+ */
+ @JvmStatic
+ fun getAppUid(context: Context, packageName: String?): String? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getApplicationInfo(packageName!!, 0)
+ pi?.uid.toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取App版本码
+ *
+ * @param context 上下文
+ * @return App版本码
+ */
+ @JvmStatic
+ fun getAppVersionCode(context: Context): Int {
+ return getAppVersionCode(context, context.packageName)
+ }
+
+ /**
+ * 获取App版本码
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App版本码
+ */
+ @JvmStatic
+ fun getAppVersionCode(context: Context, packageName: String?): Int {
+ return if (TextUtils.isEmpty(packageName)) -1 else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, 0)
+ pi?.versionCode ?: -1
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ -1
+ }
+ }
+
+ /**
+ * 判断App是否是Debug版本
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isAppDebug(context: Context): Boolean {
+ return isAppDebug(context, context.packageName)
+ }
+
+ /**
+ * 判断App是否是Debug版本
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isAppDebug(context: Context, packageName: String?): Boolean {
+ return if (TextUtils.isEmpty(packageName)) false else try {
+ val pm = context.packageManager
+ val ai = pm.getApplicationInfo(packageName!!, 0)
+ ai != null && ai.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ false
+ }
+ }
+
+
+
+ /**
+ * 获取App签名
+ *
+ * @param context 上下文
+ * @return App签名
+ */
+ @JvmStatic
+ fun getAppSignature(context: Context): Array? {
+ return getAppSignature(context, context.packageName)
+ }
+
+ /**
+ * 获取App签名
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return App签名
+ */
+ @JvmStatic
+ @SuppressLint("PackageManagerGetSignatures")
+ fun getAppSignature(context: Context, packageName: String?): Array? {
+ return if (TextUtils.isEmpty(packageName)) null else try {
+ val pm = context.packageManager
+ val pi = pm.getPackageInfo(packageName!!, PackageManager.GET_SIGNATURES)
+ pi?.signatures
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * 获取应用签名的的SHA1值
+ *
+ * 可据此判断高德,百度地图key是否正确
+ *
+ * @param context 上下文
+ * @return 应用签名的SHA1字符串, 比如:53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
+ */
+ @JvmStatic
+ fun getAppSignatureSHA1(context: Context,type:String): String? {
+ return getAppSignatureSHA1(context, type,context.packageName)
+ }
+
+ /**
+ * 获取应用签名的的SHA1值
+ *
+ * 可据此判断高德,百度地图key是否正确
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return 应用签名的SHA1字符串, 比如:53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
+ */
+ @JvmStatic
+ fun getAppSignatureSHA1(context: Context,type:String, packageName: String?): String? {
+ val signature = getAppSignature(context, packageName) ?: return null
+ return MxcEncryptTool.encryptSHA1ToString(type,signature[0].toByteArray())
+ .replace("(?<=[0-9A-F]{2})[0-9A-F]{2}".toRegex(), ":$0")
+ }
+
+ /**
+ * 判断App是否处于前台
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isAppForeground(context: Context): Boolean {
+ val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val infos = manager.runningAppProcesses
+ if (infos == null || infos.size == 0) return false
+ for (info in infos) {
+ if (info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
+ return info.processName == context.packageName
+ }
+ }
+ return false
+ }
+
+
+ /**
+ * 获取当前App信息
+ *
+ * AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序)
+ *
+ * @param context 上下文
+ * @return 当前应用的AppInfo
+ */
+ @JvmStatic
+ fun getAppInfo(context: Context): AppInfo? {
+ val pm = context.packageManager
+ var pi: PackageInfo? = null
+ try {
+ pi = pm.getPackageInfo(context.applicationContext.packageName, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
+ return pi?.let { getBean(pm, it) }
+ }
+
+ /**
+ * 得到AppInfo的Bean
+ *
+ * @param pm 包的管理
+ * @param pi 包的信息
+ * @return AppInfo类
+ */
+ @JvmStatic
+ private fun getBean(pm: PackageManager, pi: PackageInfo): AppInfo {
+ val ai = pi.applicationInfo
+ val name = ai.loadLabel(pm).toString()
+ val icon = ai.loadIcon(pm)
+ val packageName = pi.packageName
+ val packagePath = ai.sourceDir
+ val versionName = pi.versionName
+ val firstInstallTime = pi.firstInstallTime.toString()
+ val lastUpdateTime = pi.lastUpdateTime.toString()
+ val versionCode = pi.versionCode
+ val isSD = ApplicationInfo.FLAG_SYSTEM and ai.flags != ApplicationInfo.FLAG_SYSTEM
+ val isUser = ApplicationInfo.FLAG_SYSTEM and ai.flags != ApplicationInfo.FLAG_SYSTEM
+ return AppInfo(name, icon, packageName, packagePath, versionName,firstInstallTime,lastUpdateTime, versionCode, isSD, isUser)
+ }
+
+ /**
+ * 获取所有已安装App信息
+ *
+ * [.getBean](名称,图标,包名,包路径,版本号,版本Code,是否安装在SD卡,是否是用户程序)
+ *
+ * 依赖上面的getBean方法
+ *
+ * @param context 上下文
+ * @return 所有已安装的AppInfo列表
+ */
+ @JvmStatic
+ fun getAllAppsInfo(context: Context): List {
+ val list: MutableList = ArrayList()
+ val pm = context.packageManager
+ // 获取系统中安装的所有软件信息
+ val installedPackages = pm.getInstalledPackages(0)
+ for (pi in installedPackages) {
+ if (pi != null) {
+ list.add(getBean(pm, pi))
+ }
+ }
+ return list
+ }
+
+ /**
+ * 判断当前App处于前台还是后台
+ *
+ * 需添加权限 ``
+ *
+ * 并且必须是系统应用该方法才有效
+ *
+ * @param context 上下文
+ * @return `true`: 后台
`false`: 前台
+ */
+ @JvmStatic
+ fun isAppBackground(context: Context): Boolean {
+ val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val tasks = am.getRunningTasks(1)
+ if (!tasks.isEmpty()) {
+ val topActivity = tasks[0].topActivity
+ return topActivity!!.packageName != context.packageName
+ }
+ return false
+ }
+
+
+ /**
+ * 封装App信息的Bean类
+ */
+ class AppInfo(
+ name: String?, icon: Drawable?, packageName: String?, packagePath: String?,
+ versionName: String?,firstInstallTime: String?,lastUpdateTime: String?, versionCode: Int, isSD: Boolean, isUser: Boolean
+ ) {
+ var name: String? = null
+ var icon: Drawable? = null
+ var packageName: String? = null
+ var packagePath: String? = null
+ var firstInstallTime: String? = null
+ var lastUpdateTime: String? = null
+ var versionName: String? = null
+ var versionCode = 0
+ var isSD = false
+ var isUser = false
+
+ // public String toString() {
+ // return getName() + "\n"
+ // + getIcon() + "\n"
+ // + getPackageName() + "\n"
+ // + getPackagePath() + "\n"
+ // + getVersionName() + "\n"
+ // + getVersionCode() + "\n"
+ // + isSD() + "\n"
+ // + isUser() + "\n";
+ // }
+ /**
+ * @param name 名称
+ * @param icon 图标
+ * @param packageName 包名
+ * @param packagePath 包路径
+ * @param versionName 版本号
+ * @param versionCode 版本Code
+ * @param isSD 是否安装在SD卡
+ * @param isUser 是否是用户程序
+ */
+ init {
+ this.name = name
+ this.icon = icon
+ this.packageName = packageName
+ this.packagePath = packagePath
+ this.versionName = versionName
+ this.versionCode = versionCode
+ this.isSD = isSD
+ this.isUser = isUser
+ }
+ }
+}
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcBatteryUtils.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcBatteryUtils.kt
new file mode 100644
index 0000000..a2ddbc2
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcBatteryUtils.kt
@@ -0,0 +1,76 @@
+package com.ok.moxico
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.IntentFilter
+
+internal object MxcBatteryUtils {
+ @JvmStatic
+ fun getSystemBatteryLevel(context: Context?): Int {
+ val batteryInfoIntent = context!!.applicationContext
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ val level = batteryInfoIntent!!.getIntExtra("level", 0)
+ val batterySum = batteryInfoIntent.getIntExtra("scale", 100)
+ return 100 * level / batterySum
+ }
+ @JvmStatic
+ fun getSystemBatterySum(context: Context?): Int {
+ val batteryInfoIntent = context!!.applicationContext
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ return batteryInfoIntent!!.getIntExtra("scale", 100)
+ }
+ @JvmStatic
+ fun getSystemBattery(context: Context?): Int {
+ val batteryInfoIntent = context!!.applicationContext
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ val level = batteryInfoIntent!!.getIntExtra("level", 0)
+ val batterySum = batteryInfoIntent.getIntExtra("scale", 100)
+ return 100 * level / batterySum
+ }
+ @JvmStatic
+ fun getBatterytemp(context: Context?): Int {
+ val batteryInfoIntent = context!!.applicationContext
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ return batteryInfoIntent!!.getIntExtra("temperature", -1)
+ }
+ @JvmStatic
+ fun getBatteryStatus(context: Context?): Int {
+ val batteryInfoIntent = context!!.applicationContext
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ return batteryInfoIntent!!.getIntExtra("status", -1)
+ }
+ @JvmStatic
+ fun getBatteryCapacity(context: Context?): String? {
+ val mPowerProfile: Any
+ var batteryCapacity = 0.0
+ val POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile"
+ try {
+ mPowerProfile = Class.forName(POWER_PROFILE_CLASS)
+ .getConstructor(Context::class.java)
+ .newInstance(context)
+ batteryCapacity = Class
+ .forName(POWER_PROFILE_CLASS)
+ .getMethod("getBatteryCapacity")
+ .invoke(mPowerProfile) as Double
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return batteryCapacity.toString()
+ }
+
+}
\ No newline at end of file
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcDeviceTool.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcDeviceTool.kt
new file mode 100644
index 0000000..b2a3b16
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcDeviceTool.kt
@@ -0,0 +1,1947 @@
+package com.ok.moxico
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.ActivityManager
+import android.app.KeyguardManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.graphics.Bitmap
+import android.graphics.Point
+import android.net.Uri
+import android.os.*
+import android.os.Build.VERSION
+import android.os.storage.StorageManager
+import android.os.storage.StorageVolume
+import android.provider.Settings
+import android.provider.Settings.Secure
+import android.provider.Settings.SettingNotFoundException
+import android.telephony.TelephonyManager
+import android.text.TextUtils
+import android.text.format.Formatter
+import android.util.DisplayMetrics
+import android.util.Log
+import android.util.Xml
+import android.view.Surface
+import android.view.WindowManager
+import androidx.annotation.RequiresPermission
+import com.ok.moxico.MxcFileTool.Companion.sDCardPath
+import org.json.JSONObject
+import java.io.*
+import java.lang.reflect.InvocationTargetException
+import java.lang.reflect.Method
+import java.net.NetworkInterface
+import java.net.SocketException
+import java.util.*
+
+
+object MxcDeviceTool {
+
+ private var mActivityManager: ActivityManager? = null
+ private var udid: String? = ""
+ var sStatus = Status()
+
+ /**
+ * 得到屏幕的高
+ *
+ * @param context 实体
+ * @return 设备屏幕的高度
+ */
+ @JvmStatic
+ fun getScreenHeight(context: Context): Int {
+ val wm = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
+ return wm.defaultDisplay.height
+ }
+
+ /**
+ * 得到屏幕的宽
+ *
+ * @param context 实体
+ * @return 设备屏幕的宽度
+ */
+ @JvmStatic
+ fun getScreenWidth(context: Context): Int {
+ val wm = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
+ return wm.defaultDisplay.width
+ }
+
+ /**
+ * 得到设备屏幕的宽度
+ */
+ @JvmStatic
+ fun getScreenWidths(context: Context): Int {
+ val point = Point()
+ val wm = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
+ wm.defaultDisplay.getRealSize(point)
+ return point.x
+ }
+
+ fun getTotalMemory(): Long {
+ var totalMemorySize = 0L
+ val dir = "/proc/meminfo"
+ try {
+ val fr = FileReader(dir)
+ val br = BufferedReader(fr, 2048)
+ val memoryLine = br.readLine()
+ val subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:"))
+ br.close()
+ totalMemorySize = subMemoryLine.replace("\\D+".toRegex(), "").toInt().toLong()
+ } catch (var7: IOException) {
+ var7.printStackTrace()
+ }
+ return totalMemorySize
+ }
+
+ @Synchronized
+ fun getActivityManager(context: Context): ActivityManager? {
+ if (mActivityManager == null) {
+ mActivityManager =
+ context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ }
+ return mActivityManager
+ }
+
+ @JvmStatic
+ fun getUsedPercentValue(context: Context?): String? {
+ val totalMemorySize =
+ getTotalMemory()
+ val availableSize = getAvailableMemory(context) / 1024L
+ val percent =
+ ((totalMemorySize - availableSize).toFloat() / totalMemorySize.toFloat() * 100.0f).toInt()
+ return "$percent%"
+ }
+
+ @JvmStatic
+ fun getAvailableMemory(context: Context?): Long {
+ val mi = ActivityManager.MemoryInfo()
+ getActivityManager(context!!)!!
+ .getMemoryInfo(mi)
+ return mi.availMem
+ }
+
+ @JvmStatic
+ fun getTotalCpuRate(): Float {
+ return if (VERSION.RELEASE != "8" && VERSION.RELEASE != "9" && VERSION.RELEASE != "10") {
+ val totalCpuTime1 =
+ getTotalCpuTime().toFloat()
+ val totalUsedCpuTime1 =
+ totalCpuTime1 - sStatus.idletime.toFloat()
+ try {
+ Thread.sleep(360L)
+ } catch (var7: InterruptedException) {
+ var7.printStackTrace()
+ return 50.0f
+ }
+ val totalCpuTime2 =
+ getTotalCpuTime().toFloat()
+ val totalUsedCpuTime2 =
+ totalCpuTime2 - sStatus.idletime.toFloat()
+ var cpuRate =
+ 100.0f * (totalUsedCpuTime2 - totalUsedCpuTime1) / (totalCpuTime2 - totalCpuTime1)
+ val reg = Regex("^[0-9]+(.[0-9]+)?$")
+ val s = cpuRate.toString() + ""
+ cpuRate = if (s.matches(reg)) {
+ cpuRate
+ } else {
+ 0.0f
+ }
+ cpuRate
+ } else {
+ 50.0f
+ }
+ }
+
+
+ fun getTotalCpuTime(): Long {
+ return if (VERSION.RELEASE != "8" && VERSION.RELEASE != "9" && VERSION.RELEASE != "10") {
+ var cpuInfos: Array? = null
+ try {
+ val reader = BufferedReader(
+ InputStreamReader(FileInputStream("/proc/stat")),
+ 1000
+ )
+ val load = reader.readLine()
+ reader.close()
+ cpuInfos = load.split(" ".toRegex()).toTypedArray()
+ sStatus.usertime =
+ cpuInfos[2].toLong()
+ sStatus.nicetime =
+ cpuInfos[3].toLong()
+ sStatus.systemtime =
+ cpuInfos[4].toLong()
+ sStatus.idletime =
+ cpuInfos[5].toLong()
+ sStatus.iowaittime =
+ cpuInfos[6].toLong()
+ sStatus.irqtime =
+ cpuInfos[7].toLong()
+ sStatus.softirqtime =
+ cpuInfos[8].toLong()
+ } catch (var3: java.lang.Exception) {
+ var3.printStackTrace()
+ return 40L
+ }
+ sStatus.totalTime
+ } else {
+ 40L
+ }
+ }
+
+ fun getAppCpuTime(): Long {
+ var cpuInfos: Array? = null
+ cpuInfos = try {
+ val pid = Process.myPid()
+ val reader = BufferedReader(
+ InputStreamReader(FileInputStream("/proc/$pid/stat")),
+ 1000
+ )
+ val load = reader.readLine()
+ reader.close()
+ load.split(" ".toRegex()).toTypedArray()
+ } catch (var4: IOException) {
+ var4.printStackTrace()
+ return 1L
+ }
+ return cpuInfos[13].toLong() + cpuInfos[14].toLong() + cpuInfos[15]
+ .toLong() + cpuInfos[16].toLong()
+ }
+
+ @JvmStatic
+ fun getCurProcessCpuRate(): Float {
+ val totalCpuTime1 =
+ getTotalCpuTime().toFloat()
+ val processCpuTime1 =
+ getAppCpuTime().toFloat()
+ try {
+ Thread.sleep(360L)
+ } catch (var7: java.lang.Exception) {
+ return 0.0f
+ }
+ val totalCpuTime2 =
+ getTotalCpuTime().toFloat()
+ val processCpuTime2 =
+ getAppCpuTime().toFloat()
+ var cpuRate =
+ 100.0f * (processCpuTime2 - processCpuTime1) / (totalCpuTime2 - totalCpuTime1)
+ if (cpuRate > 100.0f) {
+ cpuRate = 100.0f
+ }
+ val reg = Regex("^[0-9]+(.[0-9]+)?$")
+ val s = cpuRate.toString() + ""
+ cpuRate = if (s.matches(reg)) {
+ cpuRate
+ } else {
+ 0.0f
+ }
+ return cpuRate
+ }
+
+ /**
+ * 得到设备屏幕的高度
+ */
+ @JvmStatic
+ fun getScreenHeights(context: Context): Int {
+ val point = Point()
+ val wm = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
+ wm.defaultDisplay.getRealSize(point)
+ return point.y
+ }
+
+ /**
+ * 得到设备的密度
+ */
+ @JvmStatic
+ fun getScreenDensity(context: Context, type: String): String {
+ if (type.equals("dpi")) {
+ return context.resources.displayMetrics.densityDpi.toString()
+ }
+ return context.resources.displayMetrics.density.toString()
+ }
+
+
+ /**
+ * IMEI (唯一标识序列号)
+ *
+ * 需与[.isPhone]一起使用
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文
+ * @return IMEI
+ */
+ @JvmStatic
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ fun getIMEI(context: Context): String? {
+ return getImeiOrMeid(context, true)
+ }
+
+ @JvmStatic
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ fun getMEID(context: Context): String? {
+ return getImeiOrMeid(context, false)
+ }
+
+ private fun getMinOne(s0: String, s1: String): String? {
+ val empty0 = TextUtils.isEmpty(s0)
+ val empty1 = TextUtils.isEmpty(s1)
+ return if (empty0 && empty1) {
+ ""
+ } else if (!empty0 && !empty1) {
+ if (s0.compareTo(s1) <= 0) s0 else s1
+ } else {
+ if (!empty0) s0 else s1
+ }
+ }
+
+
+ @SuppressLint("HardwareIds", "MissingPermission")
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ @JvmStatic
+ fun getImeiOrMeid(context: Context, isImei: Boolean): String? {
+ return if (VERSION.SDK_INT >= 29) {
+ ""
+ } else {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (VERSION.SDK_INT >= 26) {
+ if (isImei) {
+ var id = ""
+ try {
+ id = getMinOne(
+ tm.getImei(0),
+ tm.getImei(1)
+ )!!
+ }catch (e:Exception){
+ id = ""
+ }
+ return id
+ } else {
+ var id = ""
+ try {
+ id = getMinOne(
+ tm.getMeid(0),
+ tm.getMeid(1)
+ )!!
+ }catch (e:Exception){
+ id = ""
+ }
+ return id
+ }
+ } else {
+ val deviceId: String?
+ if (VERSION.SDK_INT >= 21) {
+ deviceId =
+ getSystemPropertyByReflect(if (isImei) "ril.gsm.imei" else "ril.cdma.meid")
+ if (!TextUtils.isEmpty(deviceId)) {
+ val idArr = deviceId!!.split(",").toTypedArray()
+ if (idArr.size == 2) getMinOne(
+ idArr[0],
+ idArr[1]
+ ) else idArr[0]
+ } else {
+ var id0 = tm.deviceId
+ var id1 = ""
+ try {
+ val method =
+ tm.javaClass.getMethod("getDeviceId", Integer.TYPE)
+ id1 = method.invoke(tm, if (isImei) 1 else 2) as String
+ } catch (var6:Exception) {
+ var6.printStackTrace()
+ }
+ if (isImei) {
+ if (id0 != null && id0.length < 15) {
+ id0 = ""
+ }
+ if (id1 != null && id1.length < 15) {
+ id1 = ""
+ }
+ } else {
+ if (id0 != null && id0.length == 14) {
+ id0 = ""
+ }
+ if (id1 != null && id1.length == 14) {
+ id1 = ""
+ }
+ }
+ getMinOne(id0, id1)
+ }
+ } else {
+ deviceId = tm.deviceId
+ if (isImei) {
+ if (deviceId != null && deviceId.length >= 15) {
+ return deviceId
+ }
+ } else if (deviceId != null && deviceId.length == 14) {
+ return deviceId
+ }
+ ""
+ }
+ }
+ }
+ }
+
+
+ private fun getSystemPropertyByReflect(key: String): String? {
+ return try {
+ val clz = Class.forName("android.os.SystemProperties")
+ val getMethod = clz.getMethod(
+ "get",
+ String::class.java,
+ String::class.java
+ )
+ getMethod.invoke(clz, key, "") as String
+ } catch (var3: java.lang.Exception) {
+ ""
+ }
+ }
+
+ /**
+ * 获取设备的IMSI
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getIMSI(context: Context): String? {
+ return getSubscriberId(context)
+ }
+
+ /**
+ * 获取设备的IMEI
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ @SuppressLint("HardwareIds", "MissingPermission")
+ fun getDeviceIdIMEI(context: Context): String? {
+ val id: String
+ //android.telephony.TelephonyManager
+ val mTelephony = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ id = if (mTelephony.deviceId != null) {
+ mTelephony.deviceId
+ } else {
+ //android.provider.Settings;
+ Settings.Secure.getString(
+ context.applicationContext.contentResolver,
+ Settings.Secure.ANDROID_ID
+ )
+ }
+ return id
+ }
+
+
+ @SuppressLint("MissingPermission")
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ @JvmStatic
+ fun getIMEIOne(context: Context): String? {
+ var imei1 = ""
+ try {
+ if (VERSION.SDK_INT >= 29) {
+ return imei1
+ }
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (VERSION.SDK_INT >= 26) {
+ imei1 = tm.getImei(0)
+ }
+ } catch (var2: java.lang.Exception) {
+ }
+ return imei1
+ }
+
+ @SuppressLint("MissingPermission")
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ @JvmStatic
+ fun getIMEITwo(context: Context): String? {
+ var imei2 = ""
+ try {
+ if (VERSION.SDK_INT >= 29) {
+ return imei2
+ }
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (VERSION.SDK_INT >= 26) {
+ imei2 = tm.getImei(1)
+ }
+ } catch (var2: java.lang.Exception) {
+ }
+ return imei2
+ }
+
+ //操作系统语言
+ @JvmStatic
+ fun getCountryByLanguage(): String? {
+ return Resources.getSystem().configuration.locale.country
+ }
+
+ //国家
+ @JvmStatic
+ fun getCountryCodeByLanguage(defaultValue: String?): String? {
+ return getCountryCodeFromMap()!!.get(getCountryByLanguage())
+ ?: defaultValue
+ }
+
+ @JvmStatic
+ private fun getCountryCodeFromMap(): HashMap? {
+ var countryCodeMap: HashMap = HashMap(256)
+ countryCodeMap!!["AL"] = "+355"
+ countryCodeMap!!["DZ"] = "+213"
+ countryCodeMap["AF"] = "+93"
+ countryCodeMap["AR"] = "+54"
+ countryCodeMap["AE"] = "+971"
+ countryCodeMap["AW"] = "+297"
+ countryCodeMap["OM"] = "+968"
+ countryCodeMap["AZ"] = "+994"
+ countryCodeMap["AC"] = "+247"
+ countryCodeMap["EG"] = "+20"
+ countryCodeMap["ET"] = "+251"
+ countryCodeMap["IE"] = "+353"
+ countryCodeMap["EE"] = "+372"
+ countryCodeMap["AD"] = "+376"
+ countryCodeMap["AO"] = "+244"
+ countryCodeMap["AI"] = "+1"
+ countryCodeMap["AG"] = "+1"
+ countryCodeMap["AT"] = "+43"
+ countryCodeMap["AX"] = "+358"
+ countryCodeMap["AU"] = "+61"
+ countryCodeMap["BB"] = "+1"
+ countryCodeMap["PG"] = "+675"
+ countryCodeMap["BS"] = "+1"
+ countryCodeMap["PK"] = "+92"
+ countryCodeMap["PY"] = "+595"
+ countryCodeMap["PS"] = "+970"
+ countryCodeMap["BH"] = "+973"
+ countryCodeMap["PA"] = "+507"
+ countryCodeMap["BR"] = "+55"
+ countryCodeMap["BY"] = "+375"
+ countryCodeMap["BM"] = "+1"
+ countryCodeMap["BG"] = "+359"
+ countryCodeMap["MP"] = "+1"
+ countryCodeMap["BJ"] = "+229"
+ countryCodeMap["BE"] = "+32"
+ countryCodeMap["IS"] = "+354"
+ countryCodeMap["PR"] = "+1"
+ countryCodeMap["PL"] = "+48"
+ countryCodeMap["BA"] = "+387"
+ countryCodeMap["BO"] = "+591"
+ countryCodeMap["BZ"] = "+501"
+ countryCodeMap["BW"] = "+267"
+ countryCodeMap["BT"] = "+975"
+ countryCodeMap["BF"] = "+226"
+ countryCodeMap["BI"] = "+257"
+ countryCodeMap["KP"] = "+850"
+ countryCodeMap["GQ"] = "+240"
+ countryCodeMap["DK"] = "+45"
+ countryCodeMap["DE"] = "+49"
+ countryCodeMap["TL"] = "+670"
+ countryCodeMap["TG"] = "+228"
+ countryCodeMap["DO"] = "+1"
+ countryCodeMap["DM"] = "+1"
+ countryCodeMap["RU"] = "+7"
+ countryCodeMap["EC"] = "+593"
+ countryCodeMap["ER"] = "+291"
+ countryCodeMap["FR"] = "+33"
+ countryCodeMap["FO"] = "+298"
+ countryCodeMap["PF"] = "+689"
+ countryCodeMap["GF"] = "+594"
+ countryCodeMap["VA"] = "+39"
+ countryCodeMap["PH"] = "+63"
+ countryCodeMap["FJ"] = "+679"
+ countryCodeMap["FI"] = "+358"
+ countryCodeMap["CV"] = "+238"
+ countryCodeMap["FK"] = "+500"
+ countryCodeMap["GM"] = "+220"
+ countryCodeMap["CG"] = "+242"
+ countryCodeMap["CD"] = "+243"
+ countryCodeMap["CO"] = "+57"
+ countryCodeMap["CR"] = "+506"
+ countryCodeMap["GG"] = "+44"
+ countryCodeMap["GD"] = "+1"
+ countryCodeMap["GL"] = "+299"
+ countryCodeMap["GE"] = "+995"
+ countryCodeMap["CU"] = "+53"
+ countryCodeMap["GP"] = "+590"
+ countryCodeMap["GU"] = "+1"
+ countryCodeMap["GY"] = "+592"
+ countryCodeMap["KZ"] = "+7"
+ countryCodeMap["HT"] = "+509"
+ countryCodeMap["KR"] = "+82"
+ countryCodeMap["NL"] = "+31"
+ countryCodeMap["BQ"] = "+599"
+ countryCodeMap["SX"] = "+1"
+ countryCodeMap["ME"] = "+382"
+ countryCodeMap["HN"] = "+504"
+ countryCodeMap["KI"] = "+686"
+ countryCodeMap["DJ"] = "+253"
+ countryCodeMap["KG"] = "+996"
+ countryCodeMap["GN"] = "+224"
+ countryCodeMap["GW"] = "+245"
+ countryCodeMap["CA"] = "+1"
+ countryCodeMap["GH"] = "+233"
+ countryCodeMap["GA"] = "+241"
+ countryCodeMap["KH"] = "+855"
+ countryCodeMap["CZ"] = "+420"
+ countryCodeMap["ZW"] = "+263"
+ countryCodeMap["CM"] = "+237"
+ countryCodeMap["QA"] = "+974"
+ countryCodeMap["KY"] = "+1"
+ countryCodeMap["CC"] = "+61"
+ countryCodeMap["KM"] = "+269"
+ countryCodeMap["XK"] = "+383"
+ countryCodeMap["CI"] = "+225"
+ countryCodeMap["KW"] = "+965"
+ countryCodeMap["HR"] = "+385"
+ countryCodeMap["KE"] = "+254"
+ countryCodeMap["CK"] = "+682"
+ countryCodeMap["CW"] = "+599"
+ countryCodeMap["LV"] = "+371"
+ countryCodeMap["LS"] = "+266"
+ countryCodeMap["LA"] = "+856"
+ countryCodeMap["LB"] = "+961"
+ countryCodeMap["LT"] = "+370"
+ countryCodeMap["LR"] = "+231"
+ countryCodeMap["LY"] = "+218"
+ countryCodeMap["LI"] = "+423"
+ countryCodeMap["RE"] = "+262"
+ countryCodeMap["LU"] = "+352"
+ countryCodeMap["RW"] = "+250"
+ countryCodeMap["RO"] = "+40"
+ countryCodeMap["MG"] = "+261"
+ countryCodeMap["IM"] = "+44"
+ countryCodeMap["MV"] = "+960"
+ countryCodeMap["MT"] = "+356"
+ countryCodeMap["MW"] = "+265"
+ countryCodeMap["MY"] = "+60"
+ countryCodeMap["ML"] = "+223"
+ countryCodeMap["MK"] = "+389"
+ countryCodeMap["MH"] = "+692"
+ countryCodeMap["MQ"] = "+596"
+ countryCodeMap["YT"] = "+262"
+ countryCodeMap["MU"] = "+230"
+ countryCodeMap["MR"] = "+222"
+ countryCodeMap["US"] = "+1"
+ countryCodeMap["AS"] = "+1"
+ countryCodeMap["VI"] = "+1"
+ countryCodeMap["MN"] = "+976"
+ countryCodeMap["MS"] = "+1"
+ countryCodeMap["BD"] = "+880"
+ countryCodeMap["PE"] = "+51"
+ countryCodeMap["FM"] = "+691"
+ countryCodeMap["MM"] = "+95"
+ countryCodeMap["MD"] = "+373"
+ countryCodeMap["MA"] = "+212"
+ countryCodeMap["MC"] = "+377"
+ countryCodeMap["MZ"] = "+258"
+ countryCodeMap["MX"] = "+52"
+ countryCodeMap["NA"] = "+264"
+ countryCodeMap["ZA"] = "+27"
+ countryCodeMap["SS"] = "+211"
+ countryCodeMap["NR"] = "+674"
+ countryCodeMap["NI"] = "+505"
+ countryCodeMap["NP"] = "+977"
+ countryCodeMap["NE"] = "+227"
+ countryCodeMap["NG"] = "+234"
+ countryCodeMap["NU"] = "+683"
+ countryCodeMap["NO"] = "+47"
+ countryCodeMap["NF"] = "+672"
+ countryCodeMap["PW"] = "+680"
+ countryCodeMap["PT"] = "+351"
+ countryCodeMap["JP"] = "+81"
+ countryCodeMap["SE"] = "+46"
+ countryCodeMap["CH"] = "+41"
+ countryCodeMap["SV"] = "+503"
+ countryCodeMap["WS"] = "+685"
+ countryCodeMap["RS"] = "+381"
+ countryCodeMap["SL"] = "+232"
+ countryCodeMap["SN"] = "+221"
+ countryCodeMap["CY"] = "+357"
+ countryCodeMap["SC"] = "+248"
+ countryCodeMap["SA"] = "+966"
+ countryCodeMap["BL"] = "+590"
+ countryCodeMap["CX"] = "+61"
+ countryCodeMap["ST"] = "+239"
+ countryCodeMap["SH"] = "+290"
+ countryCodeMap["PN"] = "+870"
+ countryCodeMap["KN"] = "+1"
+ countryCodeMap["LC"] = "+1"
+ countryCodeMap["MF"] = "+590"
+ countryCodeMap["SM"] = "+378"
+ countryCodeMap["PM"] = "+508"
+ countryCodeMap["VC"] = "+1"
+ countryCodeMap["LK"] = "+94"
+ countryCodeMap["SK"] = "+421"
+ countryCodeMap["SI"] = "+386"
+ countryCodeMap["SJ"] = "+47"
+ countryCodeMap["SZ"] = "+268"
+ countryCodeMap["SD"] = "+249"
+ countryCodeMap["SR"] = "+597"
+ countryCodeMap["SB"] = "+677"
+ countryCodeMap["SO"] = "+252"
+ countryCodeMap["TJ"] = "+992"
+ countryCodeMap["TH"] = "+66"
+ countryCodeMap["TZ"] = "+255"
+ countryCodeMap["TO"] = "+676"
+ countryCodeMap["TC"] = "+1"
+ countryCodeMap["TA"] = "+290"
+ countryCodeMap["TT"] = "+1"
+ countryCodeMap["TN"] = "+216"
+ countryCodeMap["TV"] = "+688"
+ countryCodeMap["TR"] = "+90"
+ countryCodeMap["TM"] = "+993"
+ countryCodeMap["TK"] = "+690"
+ countryCodeMap["WF"] = "+681"
+ countryCodeMap["VU"] = "+678"
+ countryCodeMap["GT"] = "+502"
+ countryCodeMap["VE"] = "+58"
+ countryCodeMap["BN"] = "+673"
+ countryCodeMap["UG"] = "+256"
+ countryCodeMap["UA"] = "+380"
+ countryCodeMap["UY"] = "+598"
+ countryCodeMap["UZ"] = "+998"
+ countryCodeMap["GR"] = "+30"
+ countryCodeMap["ES"] = "+34"
+ countryCodeMap["EH"] = "+212"
+ countryCodeMap["SG"] = "+65"
+ countryCodeMap["NC"] = "+687"
+ countryCodeMap["NZ"] = "+64"
+ countryCodeMap["HU"] = "+36"
+ countryCodeMap["SY"] = "+963"
+ countryCodeMap["JM"] = "+1"
+ countryCodeMap["AM"] = "+374"
+ countryCodeMap["YE"] = "+967"
+ countryCodeMap["IQ"] = "+964"
+ countryCodeMap["UM"] = "+1"
+ countryCodeMap["IR"] = "+98"
+ countryCodeMap["IL"] = "+972"
+ countryCodeMap["IT"] = "+39"
+ countryCodeMap["IN"] = "+91"
+ countryCodeMap["ID"] = "+62"
+ countryCodeMap["GB"] = "+44"
+ countryCodeMap["VG"] = "+1"
+ countryCodeMap["IO"] = "+246"
+ countryCodeMap["JO"] = "+962"
+ countryCodeMap["VN"] = "+84"
+ countryCodeMap["ZM"] = "+260"
+ countryCodeMap["JE"] = "+44"
+ countryCodeMap["TD"] = "+235"
+ countryCodeMap["GI"] = "+350"
+ countryCodeMap["CL"] = "+56"
+ countryCodeMap["CF"] = "+236"
+ countryCodeMap["CN"] = "+86"
+ countryCodeMap["MO"] = "+853"
+ countryCodeMap["TW"] = "+886"
+ countryCodeMap["HK"] = "+852"
+ return countryCodeMap
+ }
+
+ /**
+ * 获取ISO标准的国家码,即国际长途区号
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getNetworkCountryIso(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.networkCountryIso
+ }
+
+ /**
+ * 获取设备的 MCC + MNC
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getNetworkOperator(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.networkOperator
+ }
+
+ /**
+ * 获取(当前已注册的用户)的名字
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getNetworkOperatorName(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.networkOperatorName
+ }
+
+ /**
+ * 获取当前使用的网络类型
+ *
+ * @param context
+ * @return
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getNetworkType(context: Context): Int {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.networkType
+ }
+
+ /**
+ * 获取手机类型
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getPhoneType(context: Context): Int {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.phoneType
+ }
+
+ /**
+ * 获取SIM卡的国家码
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getSimCountryIso(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.simCountryIso
+ }
+
+ /**
+ * 获取SIM卡提供的移动国家码和移动网络码.5或6位的十进制数字
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getSimOperator(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.simOperator
+ }
+
+ /**
+ * 获取服务商名称
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getSimOperatorName(context: Context): String {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.simOperatorName
+ }
+
+ /**
+ * 获取SIM卡的序列号
+ *
+ * @param context
+ * @return
+ */
+ @SuppressLint("HardwareIds", "MissingPermission")
+ @JvmStatic
+ fun getSimSerialNumber(context: Context): String? {
+ try {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (TextUtils.isEmpty(tm.simSerialNumber)) {
+ return ""
+ } else {
+ return tm.simSerialNumber
+ }
+ } catch (var1: Exception) {
+ return ""
+ }
+ }
+
+ @SuppressLint("HardwareIds", "MissingPermission")
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ @JvmStatic
+ fun getDeviceId(context: Context): String? {
+ return if (VERSION.SDK_INT >= 29) {
+ ""
+ } else {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ val deviceId = tm.deviceId
+ if (!TextUtils.isEmpty(deviceId)) {
+ deviceId
+ } else if (VERSION.SDK_INT >= 26) {
+ val imei = tm.imei
+ if (!TextUtils.isEmpty(imei)) {
+ imei
+ } else {
+ val meid = tm.meid
+ if (TextUtils.isEmpty(meid)) "" else meid
+ }
+ } else {
+ ""
+ }
+ }
+ }
+
+ /**
+ * 获取SIM的状态信息
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getSimState(context: Context): Boolean {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.simState == 5
+ }
+
+ /**
+ * 获取唯一的用户ID
+ *
+ * @param context
+ * @return
+ */
+ @SuppressLint("HardwareIds", "MissingPermission")
+ @JvmStatic
+ fun getSubscriberId(context: Context): String? {
+ try {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (TextUtils.isEmpty(tm.subscriberId)) {
+ return ""
+ } else {
+ return tm.subscriberId
+ }
+ } catch (e: Exception) {
+ return ""
+ }
+ }
+
+ /**
+ * 获取ANDROID ID
+ *
+ * @param context
+ * @return
+ */
+ @SuppressLint("HardwareIds")
+ @JvmStatic
+ fun getAndroidId(context: Context): String {
+ return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
+ }// Galaxy nexus 品牌类型
+
+ /**
+ * 获取设备型号,如MI2SC
+ *
+ * @return 设备型号
+ */
+ @JvmStatic
+ val buildBrandModel: String
+ get() = Build.MODEL // Galaxy nexus 品牌类型
+
+ //google
+ @JvmStatic
+ val buildBrand: String
+ get() = Build.BRAND //google
+// samsung 品牌
+
+ /**
+ * 获取设备厂商,如Xiaomi
+ *
+ * @return 设备厂商
+ */
+ @JvmStatic
+ val buildMANUFACTURER: String
+ get() = Build.MANUFACTURER // samsung 品牌
+
+
+ @SuppressLint("HardwareIds", "MissingPermission")
+ @RequiresPermission("android.permission.READ_PHONE_STATE")
+ @JvmStatic
+ fun getSerial(): String? {
+ return if (VERSION.SDK_INT >= 29) {
+ try {
+ Build.getSerial()
+ } catch (var1: SecurityException) {
+ ""
+ }
+ } else {
+ if (VERSION.SDK_INT >= 26) Build.getSerial() else Build.SERIAL
+ }
+ }
+
+ /**
+ * 序列号
+ *
+ * @return
+ */
+ @JvmStatic
+ val serialNumber: String?
+ @SuppressLint("PrivateApi", "HardwareIds")
+ get() {
+ var serial: String? = null
+ try {
+ val c = Class.forName("android.os.SystemProperties")
+ val get = c.getMethod("get", String::class.java)
+ serial = get.invoke(c, "ro.serialno") as String
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return serial
+ }
+
+ /**
+ * 获取App版本名称
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getAppVersionName(context: Context?): String {
+ // 获取packagemanager的实例
+ val packageManager = context?.packageManager
+ // getPackageName()是你当前类的包名,0代表是获取版本信息
+ var packInfo: PackageInfo? = null
+ try {
+ packInfo = packageManager?.getPackageInfo(context.packageName, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
+ return packInfo!!.versionName
+ }
+
+ @JvmStatic
+ fun getABIs(): Array {
+ return if (VERSION.SDK_INT >= 21) {
+ Build.SUPPORTED_ABIS
+ } else {
+ if (!TextUtils.isEmpty(Build.CPU_ABI2)) arrayOf(
+ Build.CPU_ABI,
+ Build.CPU_ABI2
+ ) else arrayOf(Build.CPU_ABI)
+ }
+ }
+
+ @JvmStatic
+ fun isTablet(): Boolean {
+ return Resources.getSystem()
+ .configuration.screenLayout and 15 >= 3
+ }
+
+ @JvmStatic
+ fun isAdbEnabled(context: Context): Boolean {
+ return Secure.getInt(
+ context.contentResolver,
+ "adb_enabled",
+ 0
+ ) > 0
+ }
+
+ @JvmStatic
+ fun isEmulator(context: Context): Boolean {
+ val checkProperty =
+ Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.toLowerCase()
+ .contains("vbox") || Build.FINGERPRINT.toLowerCase()
+ .contains("test-keys") || Build.MODEL.contains("google_sdk") || Build.MODEL.contains(
+ "Emulator"
+ ) || Build.MODEL.contains("Android SDK built for x86") || Build.MANUFACTURER.contains("Genymotion") || Build.BRAND.startsWith(
+ "generic"
+ ) && Build.DEVICE.startsWith("generic") || "google_sdk" == Build.PRODUCT
+ return if (checkProperty) {
+ true
+ } else {
+ var operatorName = ""
+ val tm = context
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ if (tm != null) {
+ val name = tm.networkOperatorName
+ if (name != null) {
+ operatorName = name
+ }
+ }
+ val checkOperatorName = operatorName.toLowerCase() == "android"
+ if (checkOperatorName) {
+ true
+ } else {
+ val url = "tel:123456"
+ val intent = Intent()
+ intent.data = Uri.parse(url)
+ intent.action = "android.intent.action.DIAL"
+ intent.resolveActivity(
+ context.applicationContext.packageManager
+ ) == null
+ }
+ }
+ }
+
+ /**
+ * 检查权限
+ *
+ * @param context
+ * @param permission 例如 Manifest.permission.READ_PHONE_STATE
+ * @return
+ */
+ @JvmStatic
+ fun checkPermission(context: Context, permission: String): Boolean {
+ var result = false
+ if (Build.VERSION.SDK_INT >= 23) {
+ result = try {
+ val clazz = Class.forName("android.content.Context")
+ val method = clazz.getMethod("checkSelfPermission", String::class.java)
+ val rest = method.invoke(context, permission) as Int
+ rest == PackageManager.PERMISSION_GRANTED
+ } catch (e: Exception) {
+ false
+ }
+ } else {
+ val pm = context.packageManager
+ if (pm.checkPermission(
+ permission,
+ context.packageName
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ result = true
+ }
+ }
+ return result
+ }
+
+ /**
+ * 获取设备信息
+ *
+ * @param context
+ * @return
+ */
+ @JvmStatic
+ fun getDeviceInfo(context: Context): String? {
+ try {
+ val json = JSONObject()
+ val tm = context
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ var device_id: String? = null
+ if (checkPermission(context, Manifest.permission.READ_PHONE_STATE)) {
+ device_id = getDeviceIdIMEI(context)
+ }
+ var mac: String? = null
+ var fstream: FileReader? = null
+ fstream = try {
+ FileReader("/sys/class/net/wlan0/address")
+ } catch (e: FileNotFoundException) {
+ FileReader("/sys/class/net/eth0/address")
+ }
+ var `in`: BufferedReader? = null
+ if (fstream != null) {
+ try {
+ `in` = BufferedReader(fstream, 1024)
+ mac = `in`.readLine()
+ } catch (e: IOException) {
+ } finally {
+ if (fstream != null) {
+ try {
+ fstream.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ if (`in` != null) {
+ try {
+ `in`.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ }
+ json.put("mac", mac)
+ if (TextUtils.isEmpty(device_id)) {
+ device_id = mac
+ }
+ if (TextUtils.isEmpty(device_id)) {
+ device_id = Settings.Secure.getString(
+ context.contentResolver,
+ Settings.Secure.ANDROID_ID
+ )
+ }
+ json.put("device_id", device_id)
+ return json.toString()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return ""
+ }
+
+ /**
+ * 遍历LOG输出HashMap
+ *
+ * @param res
+ */
+ @JvmStatic
+ fun ThroughArray(res: HashMap<*, *>) {
+ val ite: Iterator<*> = res.entries.iterator()
+ while (ite.hasNext()) {
+ val entry = ite.next() as Map.Entry<*, *>
+ val key = entry.key!!
+ val value = entry.value!!
+ }
+ }
+
+ /**
+ * 获取设备MAC地址
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文
+ * @return MAC地址
+ */
+// @JvmStatic
+// fun getMacAddress(context: Context): String {
+// val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
+// val info = wifi.connectionInfo
+// if (info != null) {
+// val macAddress = info.macAddress
+// if (macAddress != null) {
+// return macAddress.replace(":", "")
+// }
+// }
+// return ""
+// }
+
+ @JvmStatic
+ fun getMacAddress(context: Context): String {
+ var macAddress = ""
+ var networkInterface: NetworkInterface? = null
+ try {
+ if (NetworkInterface.getByName("eth0") != null) {
+ networkInterface = NetworkInterface.getByName("eth0")
+ } else if (NetworkInterface.getByName("wlan0") != null) {
+ networkInterface = NetworkInterface.getByName("wlan0")
+ }
+
+ if (networkInterface == null) {
+ return macAddress
+ }
+ var macArr = networkInterface.hardwareAddress
+ val buf = StringBuilder()
+ for (b in macArr) {
+ buf.append(String.format("%02X", b) + ":")
+ }
+ macAddress = buf.toString()
+ return macAddress.substring(0, macAddress.length - 1)
+ } catch (e: Exception) {
+ }
+ return macAddress
+ }
+
+ /**
+ * 获取设备MAC地址
+ *
+ * 需添加权限 ``
+ *
+ * @return MAC地址
+ */
+ val macAddress: String
+ get() {
+ var macAddress = ""
+ var networkInterface: NetworkInterface? = null
+ try {
+ if (NetworkInterface.getByName("eth0") != null) {
+ networkInterface = NetworkInterface.getByName("eth0")
+ } else if (NetworkInterface.getByName("wlan0") != null) {
+ networkInterface = NetworkInterface.getByName("wlan0")
+ }
+ } catch (e: SocketException) {
+ e.printStackTrace()
+ }
+ if (networkInterface == null) {
+ return macAddress
+ }
+ var macArr = ByteArray(0)
+ try {
+ macArr = networkInterface.hardwareAddress
+ } catch (e: SocketException) {
+ e.printStackTrace()
+ }
+ val buf = StringBuilder()
+ for (b in macArr) {
+ buf.append(String.format("%02X", b))
+ }
+ macAddress = buf.toString()
+ Log.d("mac", "interfaceName=" + networkInterface.name + ", mac=" + macAddress)
+ macAddress = macAddress.replace(":", "")
+ return macAddress
+ }
+
+ /**
+ * 判断设备是否是手机
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isPhone(context: Context): Boolean {
+ val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.phoneType != TelephonyManager.PHONE_TYPE_NONE
+ }
+
+ /**
+ * 获取手机状态信息
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文
+ * @return DeviceId(IMEI) = 99000311726612
+ * DeviceSoftwareVersion = 00
+ * Line1Number =
+ * NetworkCountryIso = cn
+ * NetworkOperator = 46003
+ * NetworkOperatorName = 中国电信
+ * NetworkType = 6
+ * honeType = 2
+ * SimCountryIso = cn
+ * SimOperator = 46003
+ * SimOperatorName = 中国电信
+ * SimSerialNumber = 89860315045710604022
+ * SimState = 5
+ * SubscriberId(IMSI) = 460030419724900
+ * VoiceMailNumber = *86
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getPhoneStatus(context: Context): String? {
+ val tm = context
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ var str = ""
+ str += """
+ DeviceId(IMEI) = ${getDeviceIdIMEI(context)}
+
+ """.trimIndent()
+ str += """
+ DeviceSoftwareVersion = ${tm.deviceSoftwareVersion}
+
+ """.trimIndent()
+ str += """
+ Line1Number = ${tm.line1Number}
+
+ """.trimIndent()
+ str += """
+ NetworkCountryIso = ${tm.networkCountryIso}
+
+ """.trimIndent()
+ str += """
+ NetworkOperator = ${tm.networkOperator}
+
+ """.trimIndent()
+ str += """
+ NetworkOperatorName = ${tm.networkOperatorName}
+
+ """.trimIndent()
+ str += """
+ NetworkType = ${tm.networkType}
+
+ """.trimIndent()
+ str += """
+ honeType = ${tm.phoneType}
+
+ """.trimIndent()
+ str += """
+ SimCountryIso = ${tm.simCountryIso}
+
+ """.trimIndent()
+ str += """
+ SimOperator = ${tm.simOperator}
+
+ """.trimIndent()
+ str += """
+ SimOperatorName = ${tm.simOperatorName}
+
+ """.trimIndent()
+ str += """
+ SimSerialNumber = ${tm.simSerialNumber}
+
+ """.trimIndent()
+ str += """
+ SimState = ${tm.simState}
+
+ """.trimIndent()
+ str += """
+ SubscriberId(IMSI) = ${tm.subscriberId}
+
+ """.trimIndent()
+ str += """
+ VoiceMailNumber = ${tm.voiceMailNumber}
+
+ """.trimIndent()
+ return str
+ }
+
+ /**
+ * 跳至填充好phoneNumber的拨号界面
+ *
+ * @param context 上下文
+ * @param phoneNumber 电话号码
+ */
+ @JvmStatic
+ fun dial(context: Context, phoneNumber: String) {
+ context.startActivity(Intent(Intent.ACTION_DIAL, Uri.parse("tel:$phoneNumber")))
+ }
+
+ /**
+ * 获取手机联系人
+ *
+ * 需添加权限 ``
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文;
+ * @return 联系人链表
+ */
+ @JvmStatic
+ fun getAllContactInfo(context: Context): List> {
+ SystemClock.sleep(3000)
+ val list = ArrayList>()
+ // 1.获取内容解析者
+ val resolver = context.contentResolver
+ // 2.获取内容提供者的地址:com.android.contacts
+ // raw_contacts表的地址 :raw_contacts
+ // view_data表的地址 : data
+ // 3.生成查询地址
+ val raw_uri = Uri.parse("content://com.android.contacts/raw_contacts")
+ val date_uri = Uri.parse("content://com.android.contacts/data")
+ // 4.查询操作,先查询raw_contacts,查询contact_id
+ // projection : 查询的字段
+ val cursor = resolver.query(
+ raw_uri, arrayOf("contact_id"),
+ null, null, null
+ )
+ // 5.解析cursor
+ while (cursor!!.moveToNext()) {
+ // 6.获取查询的数据
+ val contact_id = cursor.getString(0)
+ // cursor.getString(cursor.getColumnIndex("contact_id"));//getColumnIndex
+ // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候
+ // 判断contact_id是否为空
+ if (!TextUtils.isEmpty(contact_id)) { //null ""
+ // 7.根据contact_id查询view_data表中的数据
+ // selection : 查询条件
+ // selectionArgs :查询条件的参数
+ // sortOrder : 排序
+ // 空指针: 1.null.方法 2.参数为null
+ val c = resolver.query(
+ date_uri, arrayOf(
+ "data1",
+ "mimetype"
+ ), "raw_contact_id=?", arrayOf(contact_id), null
+ )
+ val map = HashMap()
+ // 8.解析c
+ while (c!!.moveToNext()) {
+ // 9.获取数据
+ val data1 = c.getString(0)
+ val mimetype = c.getString(1)
+ // 10.根据类型去判断获取的data1数据并保存
+ if (mimetype == "vnd.android.cursor.item/phone_v2") {
+ // 电话
+ map["phone"] = data1
+ } else if (mimetype == "vnd.android.cursor.item/name") {
+ // 姓名
+ map["name"] = data1
+ }
+ }
+ // 11.添加到集合中数据
+ list.add(map)
+ // 12.关闭cursor
+ c.close()
+ }
+ }
+ // 12.关闭cursor
+ cursor.close()
+ return list
+ }
+
+ /**
+ * 打开手机联系人界面点击联系人后便获取该号码
+ *
+ * 参照以下注释代码
+ */
+ @JvmStatic
+ fun getContantNum(context: Activity) {
+ Log.i("tips", "U should copy the following code.")
+ val intent = Intent()
+ intent.action = "android.intent.action.PICK"
+ intent.type = "vnd.android.cursor.dir/phone_v2"
+ context.startActivityForResult(intent, 0)
+
+ /*@Override
+ protected void onActivityResult ( int requestCode, int resultCode, Intent data){
+ super.onActivityResult(requestCode, resultCode, data);
+ if (data != null) {
+ Uri uri = data.getData();
+ String num = null;
+ // 创建内容解析者
+ ContentResolver contentResolver = getContentResolver();
+ Cursor cursor = contentResolver.query(uri,
+ null, null, null, null);
+ while (cursor.moveToNext()) {
+ num = cursor.getString(cursor.getColumnIndex("data1"));
+ }
+ cursor.close();
+ num = num.replaceAll("-", "");//替换的操作,555-6 -> 5556
+ }
+ }*/
+ }
+
+ /**
+ * 获取手机短信并保存到xml中
+ *
+ * 需添加权限 ``
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文
+ */
+ @JvmStatic
+ fun getAllSMS(context: Context) {
+ // 1.获取短信
+ // 1.1获取内容解析者
+ val resolver = context.contentResolver
+ // 1.2获取内容提供者地址 sms,sms表的地址:null 不写
+ // 1.3获取查询路径
+ val uri = Uri.parse("content://sms")
+ // 1.4.查询操作
+ // projection : 查询的字段
+ // selection : 查询的条件
+ // selectionArgs : 查询条件的参数
+ // sortOrder : 排序
+ val cursor =
+ resolver.query(uri, arrayOf("address", "date", "type", "body"), null, null, null)
+ // 设置最大进度
+ val count = cursor!!.count //获取短信的个数
+ // 2.备份短信
+ // 2.1获取xml序列器
+ val xmlSerializer = Xml.newSerializer()
+ try {
+ // 2.2设置xml文件保存的路径
+ // os : 保存的位置
+ // encoding : 编码格式
+ xmlSerializer.setOutput(FileOutputStream(File("/mnt/sdcard/backupsms.xml")), "utf-8")
+ // 2.3设置头信息
+ // standalone : 是否独立保存
+ xmlSerializer.startDocument("utf-8", true)
+ // 2.4设置根标签
+ xmlSerializer.startTag(null, "smss")
+ // 1.5.解析cursor
+ while (cursor.moveToNext()) {
+ SystemClock.sleep(1000)
+ // 2.5设置短信的标签
+ xmlSerializer.startTag(null, "sms")
+ // 2.6设置文本内容的标签
+ xmlSerializer.startTag(null, "address")
+ val address = cursor.getString(0)
+ // 2.7设置文本内容
+ xmlSerializer.text(address)
+ xmlSerializer.endTag(null, "address")
+ xmlSerializer.startTag(null, "date")
+ val date = cursor.getString(1)
+ xmlSerializer.text(date)
+ xmlSerializer.endTag(null, "date")
+ xmlSerializer.startTag(null, "type")
+ val type = cursor.getString(2)
+ xmlSerializer.text(type)
+ xmlSerializer.endTag(null, "type")
+ xmlSerializer.startTag(null, "body")
+ val body = cursor.getString(3)
+ xmlSerializer.text(body)
+ xmlSerializer.endTag(null, "body")
+ xmlSerializer.endTag(null, "sms")
+ println("address:$address date:$date type:$type body:$body")
+ }
+ xmlSerializer.endTag(null, "smss")
+ xmlSerializer.endDocument()
+ // 2.8将数据刷新到文件中
+ xmlSerializer.flush()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 设置屏幕为横屏
+ *
+ * 还有一种就是在Activity中加属性android:screenOrientation="landscape"
+ *
+ * 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
+ *
+ * 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
+ *
+ * 设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时
+ * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
+ *
+ * @param activity activity
+ */
+ @SuppressLint("SourceLockedOrientationActivity")
+ @JvmStatic
+ fun setLandscape(activity: Activity) {
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ }
+
+ /**
+ * 设置屏幕为竖屏
+ *
+ * @param activity activity
+ */
+ @SuppressLint("SourceLockedOrientationActivity")
+ @JvmStatic
+ fun setPortrait(activity: Activity) {
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ }
+
+ /**
+ * 判断是否横屏
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isLandscape(context: Context): Boolean {
+ return context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
+ }
+
+ /**
+ * 判断是否竖屏
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isPortrait(context: Context): Boolean {
+ return context.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
+ }
+
+ @JvmStatic
+ fun isFullScreen(activity: Activity): Boolean {
+ val fullScreenFlag = 1024
+ return activity.window.attributes.flags and fullScreenFlag == fullScreenFlag
+ }
+
+ /**
+ * 获取屏幕旋转角度
+ *
+ * @param activity activity
+ * @return 屏幕旋转角度
+ */
+ @JvmStatic
+ fun getScreenRotation(activity: Activity): Int {
+ return when (activity.windowManager.defaultDisplay.rotation) {
+ Surface.ROTATION_0 -> 0
+ Surface.ROTATION_90 -> 90
+ Surface.ROTATION_180 -> 180
+ Surface.ROTATION_270 -> 270
+ else -> 0
+ }
+ }
+
+ /**
+ * 获取当前屏幕截图,包含状态栏
+ *
+ * @param activity activity
+ * @return Bitmap
+ */
+ @JvmStatic
+ fun captureWithStatusBar(activity: Activity): Bitmap {
+ val view = activity.window.decorView
+ view.isDrawingCacheEnabled = true
+ view.buildDrawingCache()
+ val bmp = view.drawingCache
+ val width = getScreenWidth(activity)
+ val height = getScreenHeight(activity)
+ val ret = Bitmap.createBitmap(bmp, 0, 0, width, height)
+ view.destroyDrawingCache()
+ return ret
+ }
+
+ /**
+ * 获取DisplayMetrics对象
+ *
+ * @param context 应用程序上下文
+ * @return
+ */
+ @JvmStatic
+ fun getDisplayMetrics(context: Context): DisplayMetrics {
+ val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
+ val displayMetrics = DisplayMetrics()
+ windowManager.defaultDisplay.getMetrics(displayMetrics)
+ return displayMetrics
+ }
+
+ /**
+ * 判断是否锁屏
+ *
+ * @param context 上下文
+ * @return `true`: 是
`false`: 否
+ */
+ @JvmStatic
+ fun isScreenLock(context: Context): Boolean {
+ val km = context
+ .getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
+ return km.inKeyguardRestrictedInputMode()
+ }
+
+ @JvmStatic
+ fun getSleepDuration(context: Context): Int {
+ return try {
+ Settings.System.getInt(
+ context.applicationContext.contentResolver,
+ "screen_off_timeout"
+ )
+ } catch (var1: SettingNotFoundException) {
+ var1.printStackTrace()
+ -123
+ }
+ }
+
+ /**
+ * 设置安全窗口,禁用系统截屏。防止 App 中的一些界面被截屏,并显示在其他设备中造成信息泄漏。
+ * (常见手机设备系统截屏操作方式为:同时按下电源键和音量键。)
+ *
+ * @param activity
+ */
+ @JvmStatic
+ fun noScreenshots(activity: Activity) {
+ activity.window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
+ }
+
+ @JvmStatic
+ fun isAutoBrightnessEnabled(activity: Activity): Boolean {
+ return try {
+ val mode = Settings.System.getInt(
+ activity.applicationContext.contentResolver,
+ "screen_brightness_mode"
+ )
+ mode == 1
+ } catch (var1: SettingNotFoundException) {
+ var1.printStackTrace()
+ false
+ }
+ }
+
+ @JvmStatic
+ fun getBrightness(activity: Activity): Int {
+ return try {
+ Settings.System.getInt(
+ activity.applicationContext.contentResolver,
+ "screen_brightness"
+ )
+ } catch (var1: SettingNotFoundException) {
+ var1.printStackTrace()
+ 0
+ }
+ }
+
+ @JvmStatic
+ fun getSDCardInfo(context: Context): List? {
+ val paths: MutableList = ArrayList()
+ val sm = context
+ .getSystemService(Context.STORAGE_SERVICE) as StorageManager
+ return if (sm == null) {
+ paths
+ } else {
+ val getPathMethod: Method
+ if (VERSION.SDK_INT >= 24) {
+ val storageVolumes: List<*> = sm.storageVolumes
+ try {
+ getPathMethod = StorageVolume::class.java.getMethod("getPath")
+ val var4 = storageVolumes.iterator()
+ while (var4.hasNext()) {
+ val storageVolume = var4.next() as StorageVolume
+ val isRemovable = storageVolume.isRemovable
+ val state = storageVolume.state
+ val path =
+ getPathMethod.invoke(storageVolume) as String
+ paths.add(
+ SDCardInfo(
+ path,
+ state,
+ isRemovable,
+ readSDCard(0, context),
+ readSDCard(1, context)
+ )
+ )
+ }
+ } catch (var18: NoSuchMethodException) {
+ var18.printStackTrace()
+ } catch (var19: IllegalAccessException) {
+ var19.printStackTrace()
+ } catch (var20: InvocationTargetException) {
+ var20.printStackTrace()
+ }
+ } else {
+ try {
+ val storageVolumeClazz =
+ Class.forName("android.os.storage.StorageVolume")
+ getPathMethod = storageVolumeClazz.getMethod("getPath")
+ val isRemovableMethod =
+ storageVolumeClazz.getMethod("isRemovable")
+ val getVolumeStateMethod =
+ StorageManager::class.java.getMethod(
+ "getVolumeState",
+ String::class.java
+ )
+ val getVolumeListMethod =
+ StorageManager::class.java.getMethod("getVolumeList")
+ val result = getVolumeListMethod.invoke(sm)
+ val length = java.lang.reflect.Array.getLength(result)
+ for (i in 0 until length) {
+ val storageVolumeElement =
+ java.lang.reflect.Array.get(result, i)
+ val path =
+ getPathMethod.invoke(storageVolumeElement) as String
+ val isRemovable =
+ isRemovableMethod.invoke(storageVolumeElement) as Boolean
+ val state =
+ getVolumeStateMethod.invoke(sm, path) as String
+ paths.add(
+ SDCardInfo(
+ path,
+ state,
+ isRemovable,
+ readSDCard(0, context),
+ readSDCard(1, context)
+ )
+ )
+ }
+ } catch (var14: ClassNotFoundException) {
+ var14.printStackTrace()
+ } catch (var15: InvocationTargetException) {
+ var15.printStackTrace()
+ } catch (var16: NoSuchMethodException) {
+ var16.printStackTrace()
+ } catch (var17: IllegalAccessException) {
+ var17.printStackTrace()
+ }
+ }
+ paths
+ }
+ }
+
+ @JvmStatic
+ fun getMountedSDCardPath(context: Context): List? {
+ val path: MutableList = ArrayList()
+ val sdCardInfo =
+ getSDCardInfo(context)
+ return if (sdCardInfo != null && !sdCardInfo.isEmpty()) {
+ val var2: Iterator<*> = sdCardInfo.iterator()
+ while (var2.hasNext()) {
+ val cardInfo =
+ var2.next() as SDCardInfo
+ val state = cardInfo.state
+ if (state != null && "mounted" == state.toLowerCase()) {
+ path.add(cardInfo.path)
+ }
+ }
+ path
+ } else {
+ path
+ }
+ }
+
+ @JvmStatic
+ fun getExternalTotalSize(): Long {
+ return MxcFileTool.getFsTotalSize(sDCardPath)
+ }
+
+ @JvmStatic
+ fun getExternalAvailableSize(): Long {
+ return MxcFileTool.getFsAvailableSize(sDCardPath)
+ }
+
+ @JvmStatic
+ fun getInternalTotalSize(): Long {
+ return MxcFileTool.getFsTotalSize(
+ Environment.getDataDirectory().absolutePath
+ )
+ }
+
+ @JvmStatic
+ fun getInternalAvailableSize(): Long {
+ return MxcFileTool.getFsAvailableSize(
+ Environment.getDataDirectory().absolutePath
+ )
+ }
+
+ fun readSDCard(type: Int, context: Context): String {
+ val blockSize: Long
+ val totalBlocks: Long
+ val avaibleBlocks: Long
+ // 判断是否有插入并挂载存储卡
+ if (Environment.getExternalStorageState() ==
+ Environment.MEDIA_MOUNTED
+ ) {
+ val path = Environment.getExternalStorageDirectory()
+ val statFs = StatFs(path.path)
+ /*
+ * Build.VERSION.SDK_INT:获取当前系统版本的等级
+ * Build.VERSION_CODES.JELLY_BEAN_MR2表示安卓4.3,也就是18,这里直接写18也可以
+ * 因为getBlockSizeLong()等三个方法是安卓4.3以后才有的,所以这里需要判断当前系统版本
+ * 补充一个知识点:所有储存设备都被分成若干块,每一块都有固定大小。
+ */if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ // 获取块的数量
+ blockSize = statFs.blockSizeLong
+ // 获取一共有多少块
+ totalBlocks = statFs.blockCountLong
+ // 可以活动的块
+ avaibleBlocks = statFs.availableBlocksLong
+ if (type == 0) {
+ return formatSize(totalBlocks * blockSize, context)
+ } else {
+ return formatSize(avaibleBlocks * blockSize, context)
+ }
+ Log.i("aaaa", "总空间:" + formatSize(totalBlocks * blockSize, context))
+ Log.i("aaaa", "可用空间:" + formatSize(avaibleBlocks * blockSize, context))
+ Log.i("aaaa", "已用空间:" + formatSize(totalBlocks * blockSize
+ - avaibleBlocks * blockSize, context))
+ } else {
+ /*
+ * 黑线说明这三个API已经过时了。但是为了兼容4.3一下的系统,我们需要写上
+ */
+ blockSize = statFs.blockSize.toLong()
+ totalBlocks = statFs.blockCount.toLong()
+ avaibleBlocks = statFs.availableBlocks.toLong()
+ if (type == 0) {
+ return formatSize(totalBlocks * blockSize, context)
+ } else {
+ return formatSize(avaibleBlocks * blockSize, context)
+ }
+ Log.i("aaaa", formatSize(avaibleBlocks * blockSize, context));
+ }
+ } else {
+ return ""
+ }
+ return ""
+ }
+
+ private fun formatSize(size: Long, context: Context): String {
+ // 格式化显示的数据。
+ return Formatter.formatFileSize(context, size)
+ }
+
+ class Status {
+ var usertime: Long = 0
+ var nicetime: Long = 0
+ var systemtime: Long = 0
+ var idletime: Long = 0
+ var iowaittime: Long = 0
+ var irqtime: Long = 0
+ var softirqtime: Long = 0
+ val totalTime: Long
+ get() = usertime + nicetime + systemtime + idletime + iowaittime + irqtime + softirqtime
+ }
+
+
+ class SDCardInfo internal constructor(
+ val path: String,
+ val state: String,
+ val isRemovable: Boolean,
+ val totalSize: String,
+ val availableSize: String
+ ) {
+ override fun toString(): String {
+ return "SDCardInfo(path='$path', state='$state', isRemovable=$isRemovable, totalSize='$totalSize', availableSize='$availableSize')"
+ }
+ }
+}
\ No newline at end of file
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcDevicesUtils.java b/mexicoDevices/src/main/java/com/ok/moxico/MxcDevicesUtils.java
new file mode 100644
index 0000000..3abd2cd
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcDevicesUtils.java
@@ -0,0 +1,544 @@
+package com.ok.moxico;
+
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.input.InputManager;
+import android.net.Proxy;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Environment;
+import android.os.SystemClock;
+import android.provider.ContactsContract;
+import android.provider.MediaStore;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+import androidx.core.os.ConfigurationCompat;
+import androidx.core.os.LocaleListCompat;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.net.NetworkInterface;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class MxcDevicesUtils {
+
+ static Map map = new HashMap<>();
+
+ @SuppressLint("MissingPermission")
+ public static Map getDevicesInfo(final Activity activity) throws JSONException {
+ map.clear();
+ map.put("albs", "");
+ map.put("idfv", "");
+ map.put("idfa", "");
+ map.put("productionDate", Build.TIME);
+ map.put("audio_external", getAudioExternalNumber(activity));
+ map.put("audio_internal", getAudioInternalNumber(activity));
+ map.put("video_external", getVideoExternalNumber(activity));
+ map.put("video_internal", getVideoInternalNumber(activity));
+ map.put("images_external", getImagesExternalNumber(activity));
+ map.put("images_internal", getImagesInternalNumber(activity));
+ map.put("download_files", getDownloadFileNumber());
+ map.put("contact_group", getContactsGroupNumber(activity));
+ map.put("pic_count", Integer.parseInt((String) map.get("images_external")) + Integer.parseInt((String) map.get("images_internal")) + "");
+
+ map.put("batteryLevelMa", (Double.parseDouble(MxcBatteryUtils.getBatteryCapacity(activity)) / 100) * MxcBatteryUtils.getSystemBatteryLevel(activity));
+ map.put("batteryMaxMa", MxcBatteryUtils.getBatteryCapacity(activity) + "mAh");
+ map.put("isAcCharge", getBatteryStatus(activity).getString("is_ac_charge"));
+ map.put("isUsbCharge", getBatteryStatus(activity).getString("is_usb_charge"));
+ map.put("currentSystemTime", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new java.util.Date()));
+ map.put("isUsingProxyPort", isWifiProxy(activity) + "");
+ map.put("isUsingVpn", isDeviceInVPN() + "");
+ map.put("locale_display_language", Locale.getDefault().getLanguage());
+ map.put("locale_iso_3_country", getCountry());
+ map.put("locale_iso_3_language", getLanguage());
+ map.put("sensor_list", getSensorList(activity).toString());
+ map.put("keyboard", getKeyboard(activity));
+
+ map.put("appScreenWidth", MxcDeviceTool.getScreenWidth(activity) + "");
+ map.put("appScreenHeight", MxcDeviceTool.getScreenHeight(activity) + "");
+ map.put("screenDensity", MxcDeviceTool.getScreenDensity(activity, ""));
+ map.put("screenDensityDpi", MxcDeviceTool.getScreenDensity(activity, "dpi"));
+ map.put("fullScreen", MxcDeviceTool.isFullScreen(activity) + "");
+ map.put("landscape", MxcDeviceTool.isLandscape(activity) + "");
+
+ map.put("lastUpdateTime", MxcAppTool.getLastUpdateTime(activity));
+ map.put("appPath", MxcAppTool.getAppPath(activity));
+ map.put("sha1", MxcAppTool.getAppSignatureSHA1(activity, "SHA-1"));
+ map.put("sha256", MxcAppTool.getAppSignatureSHA1(activity, "SHA256"));
+ map.put("md5", MxcAppTool.getAppSignatureSHA1(activity, "MD5"));
+ map.put("uid", MxcAppTool.getAppUid(activity) + "");
+ map.put("screenWidth", MxcDeviceTool.getScreenWidths(activity) + "");
+ map.put("screenHeight", MxcDeviceTool.getScreenHeights(activity) + "");
+ map.put("debug", MxcAppTool.isAppDebug(activity) + "");
+ map.put("sleepDuration", MxcDeviceTool.getSleepDuration(activity) + "");
+ map.put("autoBrightnessEnabled", MxcDeviceTool.isAutoBrightnessEnabled(activity) + "");
+ map.put("brightness", MxcDeviceTool.getBrightness(activity) + "");
+ map.put("isPhone", MxcDeviceTool.isPhone(activity) + "");
+ map.put("phoneType", MxcDeviceTool.getPhoneType(activity) + "");
+ map.put("simCardReady", MxcDeviceTool.getSimState(activity) + "");
+ map.put("simOperatorName", MxcDeviceTool.getSimOperatorName(activity));
+ map.put("simOperatorByMnc", MxcDeviceTool.getSimOperator(activity));
+ map.put("simCountryIso", MxcDeviceTool.getSimCountryIso(activity));
+ map.put("networkCountryIso", MxcHardwareUtil.getNetworkCountryIso(activity));
+ map.put("systemApp", MxcAppTool.isSystemApp(activity) + "");
+ map.put("foreground", !MxcAppTool.isAppBackground(activity) + "");
+ map.put("running", "true");
+ map.put("packageName", MxcAppTool.getAppPackageName(activity));
+ map.put("name", MxcAppTool.getAppName(activity));
+ map.put("versionName", MxcAppTool.getAppVersionName(activity));
+ map.put("versionCode", MxcAppTool.getAppVersionCode(activity) + "");
+ map.put("firstInstallTime", MxcAppTool.getFirstInstallTime(activity));
+ map.put("portrait", MxcDeviceTool.isPortrait(activity) + "");
+ map.put("screenRotation", MxcDeviceTool.getScreenRotation(activity) + "");
+ map.put("screenLock", MxcDeviceTool.isScreenLock(activity) + "");
+ map.put("networkOperator", MxcHardwareUtil.getNetworkOperator(activity));
+ map.put("simSerialNumber", MxcDeviceTool.getSimSerialNumber(activity));
+ map.put("networkOperatorName", MxcNetTool.getNetworkOperatorName(activity));
+ map.put("deviceId", MxcDeviceTool.getDeviceId(activity));
+ map.put("serial", MxcDeviceTool.getSerial());
+ String imei = (MxcDeviceTool.getIMEIOne(activity) + "," + MxcDeviceTool.getIMEITwo(activity)).equals(",") ? MxcDeviceTool.getIMEI(activity) : MxcDeviceTool.getIMEIOne(activity) + "," + MxcDeviceTool.getIMEITwo(activity);
+ if (TextUtils.equals(",", imei)) {
+ imei = "";
+ }
+ if (!TextUtils.isEmpty(imei)) {
+ Log.e("imei", "imei = " + imei);
+ if (imei.endsWith(",")) {
+ imei = imei.substring(0, imei.length() - 1);
+ }
+
+ if (imei.startsWith(",")) {
+ imei = imei.substring(1);
+ }
+ }
+ map.put("imei", imei);
+ map.put("meid", MxcDeviceTool.getMEID(activity));
+ map.put("imsi", MxcDeviceTool.getIMSI(activity));
+ map.put("board", Build.BOARD);
+ map.put("buildId", Build.ID);
+ map.put("host", Build.HOST);
+ map.put("display", Build.DISPLAY);
+ map.put("radioVersion", Build.getRadioVersion());
+ map.put("fingerprint", Build.FINGERPRINT);
+ map.put("device", Build.DEVICE);
+ map.put("product", Build.PRODUCT);
+ map.put("type", Build.TYPE);
+ map.put("buildUser", Build.USER);
+ map.put("cpuAbi", Build.CPU_ABI);
+ map.put("cpuAbi2", Build.CPU_ABI2);
+ map.put("baseOS", Build.VERSION.BASE_OS);
+ map.put("bootloader", Build.BOOTLOADER);
+ map.put("brand", Build.BRAND);
+ map.put("time", Build.TIME);
+ map.put("hardware", Build.HARDWARE);
+ map.put("language", MxcDeviceTool.getCountryByLanguage());
+ map.put("country", MxcDeviceTool.getCountryCodeByLanguage("Default"));
+ map.put("sdkVersionName", Build.VERSION.RELEASE);
+ map.put("sdkVersionCode", Build.VERSION.SDK_INT + "");
+ map.put("androidID", MxcDeviceTool.getAndroidId(activity));
+ map.put("macAddress", MxcDeviceTool.getMacAddress(activity));
+ map.put("manufacturer", MxcDeviceTool.getBuildMANUFACTURER());
+ map.put("model", MxcDeviceTool.getBuildBrandModel());
+ map.put("abis", Arrays.asList(MxcDeviceTool.getABIs()) + "");
+ map.put("isTablet", MxcDeviceTool.isTablet() + "");
+ map.put("isEmulator", MxcDeviceTool.isEmulator(activity) + "");
+ map.put("sameDevice", "true");
+ map.put("connected", MxcNetTool.isNetworkAvailable(activity) + "");
+ map.put("mobileDataEnabled", MxcNetTool.getMobileDataEnabled(activity) + "");
+ String type = MxcNetTool.getNetWorkType(activity);
+ map.put("mobileData", (type.equals("NETWORK_2G") || type.equals("NETWORK_3G") || type.equals("NETWORK_4G") || type.equals("NETWORK_5G")) + "");
+ map.put("is4G", MxcNetTool.is4G(activity) + "");
+ map.put("is5G", MxcNetTool.is5G(activity) + "");
+ map.put("wifiConnected", MxcNetTool.isWifiConnected(activity) + "");
+ map.put("networkType", MxcNetTool.getNetWorkType(activity) + "");
+ map.put("ipAddress", MxcNetTool.getIPAddress(true) + "");
+ map.put("ipv6Address", MxcNetTool.getIPAddress(false));
+ map.put("ipAddressByWifi", MxcNetTool.getWifiInfo(activity, "ipAddress"));
+ map.put("gatewayByWifi", MxcNetTool.getWifiInfo(activity, "gateway"));
+ map.put("netMaskByWifi", MxcNetTool.getWifiInfo(activity, "netmask"));
+ map.put("serverAddressByWifi", MxcNetTool.getWifiInfo(activity, "serverAddress"));
+ map.put("broadcastIpAddress", MxcNetTool.getBroadcastIpAddress());
+ map.put("ssid", MxcNetTool.getSSID(activity));
+ map.put("root", MxcAppTool.isAppRoot() + "");
+ if (Build.VERSION.SDK_INT >= 17) {
+ map.put("adbEnabled", MxcDeviceTool.isAdbEnabled(activity) + "");
+ }
+ map.put("sdCardEnableByEnvironment", MxcFileTool.sdCardIsAvailable() + "");
+ map.put("sdCardPathByEnvironment", MxcFileTool.getSDCardPath());
+ map.put("sdCardInfo", MxcDeviceTool.getSDCardInfo(activity).toString());
+ map.put("mountedSdCardPath", MxcDeviceTool.getMountedSDCardPath(activity).toString());
+ map.put("externalTotalSize", MxcFileTool.byte2FitMemorySize(MxcDeviceTool.getExternalTotalSize(), 2));
+ map.put("externalAvailableSize", MxcFileTool.byte2FitMemorySize(MxcDeviceTool.getExternalAvailableSize(), 2));
+ map.put("internalTotalSize", MxcFileTool.byte2FitMemorySize(MxcDeviceTool.getInternalTotalSize(), 2));
+ map.put("internalAvailableSize", MxcFileTool.byte2FitMemorySize(MxcDeviceTool.getInternalAvailableSize()));
+ map.put("batteryLevel", MxcBatteryUtils.getSystemBatteryLevel(activity));
+ map.put("batterySum", MxcBatteryUtils.getSystemBatterySum(activity));
+ map.put("batteryPercent", MxcBatteryUtils.getSystemBattery(activity) + "%");
+ map.put("percentValue", MxcDeviceTool.getUsedPercentValue(activity));
+ map.put("availableMemory", MxcDeviceTool.getAvailableMemory(activity));
+ map.put("processCpuRate", MxcDeviceTool.getCurProcessCpuRate());
+ map.put("cpuRate", MxcDeviceTool.getTotalCpuRate());
+ map.put("time", MxcHardwareUtil.getuptime());
+ map.put("timezone", MxcHardwareUtil.getTimezone());
+ map.put("gpsEnabled", MxcHardwareUtil.isGpsEnabled(activity));
+ map.put("bootTime", MxcHardwareUtil.getBoottime());
+ map.put("batteryStatus", MxcHardwareUtil.getBatteryStatus(activity));
+ map.put("batterytemp", MxcHardwareUtil.getBatterytemp(activity));
+ map.put("isPlugged", MxcHardwareUtil.isPlugged(activity));
+ map.put("wifiBSSID", MxcHardwareUtil.getWifiBSSID(activity));
+ map.put("arpList", MxcHardwareUtil.readArp(activity));
+ map.put("bluetoothAddress", MxcHardwareUtil.getBluetoothAddress(activity));
+ map.put("countryZipCode", MxcHardwareUtil.getCountryZipCode(activity));
+ map.put("cellLocation", MxcHardwareUtil.getCellLocation(activity));
+ map.put("defaultHost", getDefaultHost());
+ map.put("voiceMailNumber", MxcHardwareUtil.getVoiceMailNumber(activity));
+ map.put("available", MxcNetTool.isAvailable(activity) + "");
+ map.put("availableByPing", MxcNetTool.isAvailableByPing() + "");
+ map.put("availableByDns", MxcNetTool.isAvailableByDns() + "");
+ map.put("wifiAvailable", MxcNetTool.isWifiAvailable(activity) + "");
+ map.put("wifiSignal", getWifiRssi(activity) + "");
+ map.put("cellularSignal", getMobileDbm(activity) + "");
+
+ map.put("ramTotalSize", CPUUtil.getRAMTotalMemorySize(activity));
+ map.put("ramUsableSize", CPUUtil.getRAMUsableMemorySize(activity));
+ map.put("memoryCardSize", CPUUtil.getTotalExternalMemorySize() + "");
+ map.put("memoryCardUsableSize", CPUUtil.getAvailableExternalMemorySize() + "");
+ map.put("memoryCardSizeUse", CPUUtil.getTotalExternalMemorySize() - CPUUtil.getAvailableExternalMemorySize() + "");
+ map.put("internalStorageUsable", CPUUtil.getAvailableInternalMemorySize() + "");
+ map.put("internalStorageTotal", CPUUtil.getTotalInternalMemorySize() + "");
+ map.put("network", CPUUtil.getNetworkData(activity) + "");
+ map.put("cpuNum", CPUUtil.getNumberOfCPUCores());
+ map.put("appMaxMemory", CPUUtil.getAPPMaxMemory(activity) + "M");
+ map.put("appAvailableMemory", CPUUtil.getAPPAvailableMemory(activity) + "M");
+ map.put("appFreeMemory", CPUUtil.getAPPFreeMemory(activity) + "M");
+ map.put("physicalSize", CPUUtil.getScreenSizeOfDevice(activity));
+ map.put("totalBootTimeWake", SystemClock.uptimeMillis());
+ map.put("totalBootTime", SystemClock.elapsedRealtime());
+// map.put("memory", CPUUtil.getMemorySize(this));
+ return map;
+ }
+
+ /**
+ * 获取手机信号强度,需添加权限 android.permission.ACCESS_COARSE_LOCATION
+ * API要求不低于17
+ *
+ * @return 当前手机主卡信号强度, 单位 dBm(-1是默认值,表示获取失败)
+ */
+ @SuppressLint("MissingPermission")
+ public static int getMobileDbm(Context context) {
+ int dbm = -1;
+ TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ List cellInfoList;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ cellInfoList = tm.getAllCellInfo();
+ if (null != cellInfoList) {
+ for (CellInfo cellInfo : cellInfoList) {
+ if (cellInfo instanceof CellInfoGsm) {
+ CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm) cellInfo).getCellSignalStrength();
+ dbm = cellSignalStrengthGsm.getDbm();
+ } else if (cellInfo instanceof CellInfoCdma) {
+ CellSignalStrengthCdma cellSignalStrengthCdma =
+ ((CellInfoCdma) cellInfo).getCellSignalStrength();
+ dbm = cellSignalStrengthCdma.getDbm();
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ CellSignalStrengthWcdma cellSignalStrengthWcdma =
+ ((CellInfoWcdma) cellInfo).getCellSignalStrength();
+ dbm = cellSignalStrengthWcdma.getDbm();
+ }
+ } else if (cellInfo instanceof CellInfoLte) {
+ CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) cellInfo).getCellSignalStrength();
+ dbm = cellSignalStrengthLte.getDbm();
+ }
+ }
+ }
+ }
+ return dbm;
+ }
+
+ public static String getDefaultHost() {
+ String proHost = "";
+ int proPort = 0;
+ try {
+ proHost = Proxy.getDefaultHost();
+ proPort = Proxy.getDefaultPort();
+ } catch (Exception var3) {
+ }
+ return proHost + " " + proPort;
+ }
+
+ public static int getWifiRssi(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ if (wifiManager != null) {
+ WifiInfo info = wifiManager.getConnectionInfo();
+ if (info != null) {
+ return info.getRssi();
+ }
+ }
+ return 0;
+ }
+
+ public static String getAudioExternalNumber(Context context) {
+ int result = 0;
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{"date_added", "date_modified", "duration", "mime_type", "is_music", "year", "is_notification", "is_ringtone", "is_alarm"}, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+
+ return String.valueOf(result);
+ }
+
+ public static String getAudioInternalNumber(Context context) {
+ int result = 0;
+
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, new String[]{"date_added", "date_modified", "duration", "mime_type", "is_music", "year", "is_notification", "is_ringtone", "is_alarm"}, (String) null, (String[]) null, "title_key"); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+
+ return String.valueOf(result);
+ }
+
+ public static String getVideoExternalNumber(Context context) {
+ int result = 0;
+ String[] arrayOfString = new String[]{"date_added"};
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, arrayOfString, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ return String.valueOf(result);
+ }
+
+ public static String getVideoInternalNumber(Context context) {
+ int result = 0;
+ String[] arrayOfString = new String[]{"date_added"};
+
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Video.Media.INTERNAL_CONTENT_URI, arrayOfString, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+
+ return String.valueOf(result);
+ }
+
+ public static String getImagesExternalNumber(Context context) {
+ int result = 0;
+
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{"datetaken", "date_added", "date_modified", "height", "width", "latitude", "longitude", "mime_type", "title", "_size"}, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ return String.valueOf(result);
+ }
+
+ public static String getImagesInternalNumber(Context context) {
+ int result = 0;
+
+ Cursor cursor;
+ for (cursor = context.getContentResolver().query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new String[]{"datetaken", "date_added", "date_modified", "height", "width", "latitude", "longitude", "mime_type", "title", "_size"}, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+
+ return String.valueOf(result);
+ }
+
+
+ public static String getDownloadFileNumber() {
+ int result = 0;
+ File[] files = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).listFiles();
+ if (files != null) {
+ result = files.length;
+ }
+
+ return String.valueOf(result);
+ }
+
+ public static String getContactsGroupNumber(Context context) {
+ try {
+ int result = 0;
+ Uri uri = ContactsContract.Groups.CONTENT_URI;
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor;
+ for (cursor = contentResolver.query(uri, (String[]) null, (String) null, (String[]) null, (String) null); cursor != null && cursor.moveToNext(); ++result) {
+ }
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ return String.valueOf(result);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public static JSONObject getBatteryStatus(Context context) {
+ JSONObject jSONObject = new JSONObject();
+ try {
+ Intent intent = context.registerReceiver((BroadcastReceiver) null, new IntentFilter("android.intent.action.BATTERY_CHANGED"));
+ int k = intent.getIntExtra("plugged", -1);
+ switch (k) {
+ case 1:
+ jSONObject.put("is_usb_charge", "false");
+ jSONObject.put("is_ac_charge", "true");
+ jSONObject.put("is_charging", "true");
+ return jSONObject;
+ case 2:
+ jSONObject.put("is_usb_charge", "true");
+ jSONObject.put("is_ac_charge", "false");
+ jSONObject.put("is_charging", "true");
+ return jSONObject;
+ default:
+ jSONObject.put("is_usb_charge", "false");
+ jSONObject.put("is_ac_charge", "false");
+ jSONObject.put("is_charging", "false");
+ return jSONObject;
+ }
+ } catch (JSONException e) {
+ Log.i("异常", e.toString());
+ }
+ return jSONObject;
+ }
+
+ private static boolean isWifiProxy(Context context) {
+ final boolean IS_ICS_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+ String proxyAddress;
+ int proxyPort;
+ if (IS_ICS_OR_LATER) {
+ proxyAddress = System.getProperty("http.proxyHost");
+ String portStr = System.getProperty("http.proxyPort");
+ proxyPort = Integer.parseInt((portStr != null ? portStr : "-1"));
+ } else {
+ proxyAddress = Proxy.getHost(context);
+ proxyPort = Proxy.getPort(context);
+ }
+ return (!TextUtils.isEmpty(proxyAddress)) && (proxyPort != -1);
+ }
+
+ //判断网络接口名字包含 ppp0 或 tun0
+ public static boolean isDeviceInVPN() {
+ try {
+ List all = Collections.list(NetworkInterface.getNetworkInterfaces());
+ for (NetworkInterface nif : all) {
+ if (nif.getName().equals("tun0") || nif.getName().equals("ppp0")) {
+ Log.i("TAG", "isDeviceInVPN current device is in VPN.");
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ @SuppressLint("NewApi")
+ private static JSONArray getSensorList(Context context) {
+ // 获取传感器管理器
+ SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+
+ // 获取全部传感器列表
+ List sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
+ JSONArray jsonArray = new JSONArray();
+ for (Sensor item : sensors) {
+ JSONObject jsonObject = new JSONObject();
+ try {
+ jsonObject.put("type", item.getType());
+ jsonObject.put("name", item.getName());
+ jsonObject.put("version", item.getVersion());
+ jsonObject.put("vendor", item.getVendor());
+ jsonObject.put("maxRange", item.getMaximumRange());
+ jsonObject.put("minDelay", item.getMinDelay());
+ jsonObject.put("power", item.getPower());
+ jsonObject.put("resolution", item.getResolution());
+ } catch (JSONException e) {
+ Log.i("json异常", e.toString());
+ }
+ jsonArray.put(jsonObject);
+ }
+ return jsonArray;
+ }
+
+ public static String getCountry() {
+ String country = "";
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ LocaleListCompat listCompat = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration());
+ for (int i = 0; i < listCompat.size(); i++) {
+ country = listCompat.get(i).getCountry();
+ }
+ } else {
+ Locale locale = Locale.getDefault();
+ country = locale.getCountry();
+ }
+ return country;
+ }
+
+ public static String getLanguage() {
+ String language = "";
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ LocaleListCompat listCompat = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration());
+ for (int i = 0; i < listCompat.size(); i++) {
+ language = listCompat.get(i).getLanguage();
+ }
+ } else {
+ Locale locale = Locale.getDefault();
+ language = locale.getLanguage();
+ }
+ return language;
+ }
+
+ public static int getKeyboard(Context context) {
+ InputManager inputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ int[] inputDeviceIds = inputManager.getInputDeviceIds();
+ return inputDeviceIds.length;
+ }
+
+}
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcEncryptTool.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcEncryptTool.kt
new file mode 100644
index 0000000..e98b988
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcEncryptTool.kt
@@ -0,0 +1,69 @@
+package com.ok.moxico
+
+
+import java.security.MessageDigest
+import java.security.NoSuchAlgorithmException
+import java.security.SecureRandom
+import javax.crypto.Cipher
+import javax.crypto.spec.SecretKeySpec
+
+
+object MxcEncryptTool {
+
+ /**
+ * SHA1加密
+ *
+ * @param data 明文字节数组
+ * @return 16进制密文
+ */
+ @JvmStatic
+ fun encryptSHA1ToString(type:String,data: ByteArray?): String {
+ return bytes2HexString(encryptSHA1(type,data))
+ }
+
+ private val HEX_DIGITS = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F')
+
+ @JvmStatic
+ fun bytes2HexString(bytes: ByteArray): String {
+ val ret = CharArray(bytes.size shl 1)
+ var i = 0
+ var j = 0
+ while (i < bytes.size) {
+ ret[j++] = HEX_DIGITS[bytes[i].toInt() ushr 4 and 0x0f]
+ ret[j++] = HEX_DIGITS[bytes[i].toInt() and 0x0f]
+ i++
+ }
+ return String(ret)
+ }
+
+ /**
+ * SHA1加密
+ *
+ * @param data 明文字节数组
+ * @return 密文字节数组
+ */
+ @JvmStatic
+ fun encryptSHA1(type:String,data: ByteArray?): ByteArray {
+ return encryptAlgorithm(data, type)
+ }
+
+ /**
+ * 对data进行algorithm算法加密
+ *
+ * @param data 明文字节数组
+ * @param algorithm 加密算法
+ * @return 密文字节数组
+ */
+ private fun encryptAlgorithm(data: ByteArray?, algorithm: String): ByteArray {
+ try {
+ val md = MessageDigest.getInstance(algorithm)
+ md.update(data)
+ return md.digest()
+ } catch (e: NoSuchAlgorithmException) {
+ e.printStackTrace()
+ }
+ return ByteArray(0)
+ }
+
+}
\ No newline at end of file
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcFileTool.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcFileTool.kt
new file mode 100644
index 0000000..0d922e9
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcFileTool.kt
@@ -0,0 +1,189 @@
+package com.ok.moxico
+
+import android.annotation.SuppressLint
+import android.annotation.TargetApi
+import android.content.ContentUris
+import android.content.ContentValues
+import android.content.Context
+import android.content.Intent
+import android.database.Cursor
+import android.net.Uri
+import android.os.Build
+import android.os.Build.VERSION
+import android.os.Environment
+import android.os.StatFs
+import android.provider.DocumentsContract
+import android.provider.MediaStore
+import android.text.TextUtils
+import android.util.Base64
+import android.util.Log
+import androidx.core.content.FileProvider
+import java.io.*
+import java.lang.Exception
+import java.nio.ByteBuffer
+import java.nio.channels.FileChannel
+import java.nio.charset.StandardCharsets
+import java.util.*
+
+
+class MxcFileTool {
+
+
+ companion object {
+
+
+
+ /**
+ * 判断SD卡是否可用
+ *
+ * @return true : 可用
false : 不可用
+ */
+ val isSDCardEnable: Boolean
+ get() = Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()
+
+ /**
+ * 获取SD卡路径
+ *
+ * 一般是/storage/emulated/0/
+ *
+ * @return SD卡路径
+ */
+ @JvmStatic
+ val sDCardPath: String
+ get() = if (!isSDCardEnable) {
+ "sdcard unable!"
+ } else Environment.getExternalStorageDirectory().path + File.separator
+
+ @JvmStatic
+ fun getFsTotalSize(anyPathInFs: String?): Long {
+ return if (TextUtils.isEmpty(anyPathInFs)) {
+ 0L
+ } else {
+ val statFs = StatFs(anyPathInFs)
+ val blockSize: Long
+ val totalSize: Long
+ try{
+ if (VERSION.SDK_INT >= 18) {
+ blockSize = statFs.blockSizeLong
+ totalSize = statFs.blockCountLong
+ } else {
+ blockSize = statFs.blockSize.toLong()
+ totalSize = statFs.blockCount.toLong()
+ }
+ blockSize * totalSize
+ }catch (e:Exception){
+ 0L
+ }
+ }
+ }
+ @JvmStatic
+ fun getFsAvailableSize(anyPathInFs: String?): Long {
+ return if (TextUtils.isEmpty(anyPathInFs)) {
+ 0L
+ } else {
+ val statFs = StatFs(anyPathInFs)
+ val blockSize: Long
+ val availableSize: Long
+ try {
+ if (VERSION.SDK_INT >= 18) {
+ blockSize = statFs.blockSizeLong
+ availableSize = statFs.availableBlocksLong
+ } else {
+ blockSize = statFs.blockSize.toLong()
+ availableSize = statFs.availableBlocks.toLong()
+ }
+ blockSize * availableSize
+ }catch (e:Exception){
+ 0L
+ }
+ }
+ }
+
+ @SuppressLint("DefaultLocale")
+ @JvmStatic
+ fun byte2FitMemorySize(byteSize: Long): String? {
+ return byte2FitMemorySize(byteSize, 3)
+ }
+ @SuppressLint("DefaultLocale")
+ @JvmStatic
+ fun byte2FitMemorySize(byteSize: Long, precision: Int): String? {
+ return if (precision < 0) {
+ throw IllegalArgumentException("precision shouldn't be less than zero!")
+ } else if (byteSize < 0L) {
+ throw IllegalArgumentException("byteSize shouldn't be less than zero!")
+ } else if (byteSize < 1024L) {
+ String.format("%." + precision + "fB", byteSize.toDouble())
+ } else if (byteSize < 1048576L) {
+ String.format(
+ "%." + precision + "fKB",
+ byteSize.toDouble() / 1024.0
+ )
+ } else {
+ if (byteSize < 1073741824L) String.format(
+ "%." + precision + "fMB",
+ byteSize.toDouble() / 1048576.0
+ ) else String.format(
+ "%." + precision + "fGB",
+ byteSize.toDouble() / 1.073741824E9
+ )
+ }
+ }
+
+ /**
+ * SD卡是否可用.
+ */
+ @JvmStatic
+ fun sdCardIsAvailable(): Boolean {
+ return if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
+ val sd = File(Environment.getExternalStorageDirectory().path)
+ sd.canWrite()
+ } else {
+ false
+ }
+ }
+
+
+
+
+
+ //----------------------------------------------------------------------------------------------
+ /**
+ * 根据文件路径获取文件
+ *
+ * @param filePath 文件路径
+ * @return 文件
+ */
+ @JvmStatic
+ fun getFileByPath(filePath: String?): File? {
+ return if (TextUtils.isEmpty(filePath)) null else File(filePath)
+ }
+ //==============================================================================================
+
+ /**
+ * 判断文件是否存在
+ *
+ * @param file 文件
+ * @return `true`: 存在
`false`: 不存在
+ */
+ @JvmStatic
+ fun isFileExists(file: File?): Boolean {
+ return file != null && file.exists()
+ }
+
+
+
+ /**
+ * 判断目录是否存在,不存在则判断是否创建成功
+ *
+ * @param file 文件
+ * @return `true`: 存在或创建成功
`false`: 不存在或创建失败
+ */
+ @JvmStatic
+ fun createOrExistsDir(file: File?): Boolean {
+ // 如果存在,是目录则返回true,是文件则返回false,不存在则返回是否创建成功
+ return file != null && if (file.exists()) file.isDirectory else file.mkdirs()
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcHardwareUtil.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcHardwareUtil.kt
new file mode 100644
index 0000000..d027b26
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcHardwareUtil.kt
@@ -0,0 +1,345 @@
+package com.ok.moxico
+
+import android.annotation.SuppressLint
+import android.bluetooth.BluetoothAdapter
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.IntentFilter
+import android.location.*
+import android.net.Proxy
+import android.net.wifi.WifiManager
+import android.os.Build.VERSION
+import android.os.Bundle
+import android.os.SystemClock
+import android.telephony.TelephonyManager
+import android.telephony.gsm.GsmCellLocation
+import android.text.TextUtils
+import android.util.Log
+import java.io.BufferedReader
+import java.io.FileReader
+import java.io.IOException
+import java.util.*
+
+
+object MxcHardwareUtil {
+ var locationListener: LocationListener = object : LocationListener {
+ override fun onLocationChanged(location: Location) {
+ Log.d("Location", "onLocationChanged")
+ Log.d("Location", "onLocationChanged Latitude" + location.latitude)
+ Log.d("Location", "onLocationChanged location" + location.longitude)
+ }
+
+ override fun onProviderDisabled(provider: String) {
+ Log.d("Location", "onProviderDisabled")
+ }
+
+ override fun onProviderEnabled(provider: String) {
+ Log.d("Location", "onProviderEnabled")
+ }
+
+ override fun onStatusChanged(
+ provider: String,
+ status: Int,
+ extras: Bundle
+ ) {
+ Log.d("Location", "onStatusChanged")
+ }
+ }
+ var ml: ArrayList = ArrayList()
+
+ @JvmStatic
+ fun getuptime(): Long {
+ var uptime = 0L
+ try {
+ if (VERSION.SDK_INT >= 17) {
+ uptime = SystemClock.elapsedRealtime()
+ }
+ } catch (var3: Exception) {
+ }
+ return uptime
+ }
+ @JvmStatic
+ val timezone: String
+ get() {
+ var timezone = ""
+ try {
+ val tz = TimeZone.getDefault()
+ timezone = tz.getDisplayName(false, 0) + ", " + tz.id
+ } catch (var2: Exception) {
+ }
+ return timezone
+ }
+ @JvmStatic
+ fun isGpsEnabled(context: Context?): Boolean {
+ val lm =context!!
+ .getSystemService(Context.LOCATION_SERVICE) as LocationManager
+ return lm.isProviderEnabled("gps")
+ }
+ @JvmStatic
+ val boottime: Long
+ get() {
+ var bootTime = 0L
+ try {
+ if (VERSION.SDK_INT >= 17) {
+ bootTime =
+ System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() / 1000000L
+ }
+ } catch (var3: Exception) {
+ }
+ return bootTime
+ }
+ @JvmStatic
+ fun getBatterytemp(context: Context?): Int {
+ var temperature = 0
+ try {
+ val batteryInfoIntent = context!!
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ temperature = batteryInfoIntent!!.getIntExtra("temperature", -1)
+ } catch (var2: Exception) {
+ }
+ return temperature
+ }
+ @JvmStatic
+ fun getBatteryStatus(context: Context?): Int {
+ var temperature = 0
+ try {
+ val batteryInfoIntent = context!!
+ .registerReceiver(
+ null as BroadcastReceiver?,
+ IntentFilter("android.intent.action.BATTERY_CHANGED")
+ )
+ temperature = batteryInfoIntent!!.getIntExtra("status", -1)
+ } catch (var2: Exception) {
+ }
+ return temperature
+ }
+ @JvmStatic
+ fun isPlugged(context: Context?): Boolean {
+ var acPlugged = false
+ var usbPlugged = false
+ var wirePlugged = false
+ try {
+ val intentFilter = IntentFilter("android.intent.action.BATTERY_CHANGED")
+ val intent = context!!
+ .registerReceiver(null as BroadcastReceiver?, intentFilter)
+ val isPlugged = intent!!.getIntExtra("plugged", -1)
+ acPlugged = 1 == isPlugged
+ usbPlugged = 2 == isPlugged
+ wirePlugged = 4 == isPlugged
+ } catch (var6: Exception) {
+ }
+ return acPlugged || usbPlugged || wirePlugged
+ }
+
+ @JvmStatic
+ fun isAcCharge(context: Context?): Int {
+ var acPlugged = false
+ var acCharge = 0
+ try {
+ val intentFilter = IntentFilter("android.intent.action.BATTERY_CHANGED")
+ val intent = context!!
+ .registerReceiver(null as BroadcastReceiver?, intentFilter)
+ val isPlugged = intent!!.getIntExtra("plugged", -1)
+ acPlugged = 2 == isPlugged
+ if (acPlugged){
+ acCharge = 1
+ }else{
+ acCharge = 0
+ }
+ } catch (var6: Exception) {
+ }
+ return acCharge
+ }
+ @JvmStatic
+ fun isUSBCharge(context: Context?): Int {
+ var acPlugged = false
+ var acCharge = 0
+ try {
+ val intentFilter = IntentFilter("android.intent.action.BATTERY_CHANGED")
+ val intent = context!!
+ .registerReceiver(null as BroadcastReceiver?, intentFilter)
+ val isPlugged = intent!!.getIntExtra("plugged", -1)
+ acPlugged = 1 == isPlugged
+ if (acPlugged){
+ acCharge = 1
+ }else{
+ acCharge = 0
+ }
+ } catch (var6: Exception) {
+ }
+ return acCharge
+ }
+ @JvmStatic
+ fun getWifiBSSID(context: Context?): String? {
+ try {
+ val wm =
+ context!!
+ .getSystemService(Context.WIFI_SERVICE) as WifiManager
+ if (wm != null) {
+ val winfo = wm.connectionInfo
+ return winfo.bssid
+ }
+ } catch (var2: Exception) {
+ }
+ return null
+ }
+ @JvmStatic
+ fun readArp(context: Context?): String {
+ ml.clear()
+ try {
+ val br =
+ BufferedReader(FileReader("/proc/net/arp"))
+ var line = ""
+ var ip = ""
+ var flag = ""
+ var mac = ""
+ while (br.readLine().also { line = it } != null) {
+ try {
+ line = line.trim { it <= ' ' }
+ if (line.length >= 63 && !line.toUpperCase(Locale.US)
+ .contains("IP")
+ ) {
+ ip = line.substring(0, 17).trim { it <= ' ' }
+ flag = line.substring(29, 32).trim { it <= ' ' }
+ mac = line.substring(41, 63).trim { it <= ' ' }
+ if (!mac.contains("00:00:00:00:00:00")) {
+ ml.add("mac=$mac ; ip= $ip ;flag= $flag")
+ }
+ }
+ } catch (var6: Exception) {
+ }
+ }
+ br.close()
+ } catch (var7: Exception) {
+ }
+ return ml.toString()
+ }
+ @JvmStatic
+ fun getBluetoothAddress(context: Context?): String? {
+ return if (VERSION.RELEASE == "10") {
+ ""
+ } else {
+ try {
+ val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
+ val field =
+ bluetoothAdapter.javaClass.getDeclaredField("mService")
+ field.isAccessible = true
+ val bluetoothManagerService = field[bluetoothAdapter]
+ if (bluetoothManagerService == null) {
+ null
+ } else {
+ val method =
+ bluetoothManagerService.javaClass.getMethod("getAddress")
+ val address = method.invoke(bluetoothManagerService)
+ if (address != null && address is String) address else null
+ }
+ } catch (var5: Exception) {
+ var5.printStackTrace()
+ ""
+ }
+ }
+ }
+ @JvmStatic
+ fun getCountryZipCode(context: Context?): String {
+ var CountryZipCode = ""
+ try {
+ val locale =
+ context!!.resources
+ .configuration.locale
+ CountryZipCode = locale.isO3Country
+ } catch (var2: Exception) {
+ }
+ return CountryZipCode
+ }
+
+ fun getSimCountryIso(context: Context?): String {
+ var simCountryIso = ""
+ try {
+ val telManager = context!!
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ simCountryIso = telManager.simCountryIso
+ } catch (var2: Exception) {
+ }
+ return simCountryIso
+ }
+ @JvmStatic
+ fun getNetworkCountryIso(context: Context?): String {
+ var networkCountryIso = ""
+ try {
+ val tel = context!!
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ networkCountryIso = tel.networkCountryIso
+ } catch (var2: Exception) {
+ }
+ return networkCountryIso
+ }
+ @JvmStatic
+ fun getSimOperator(context: Context?): String {
+ var simOperator = ""
+ try {
+ val tel = context!!
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ simOperator = tel.simOperator
+ } catch (var2: Exception) {
+ }
+ return simOperator
+ }
+ @JvmStatic
+ fun getNetworkOperator(context: Context?): String {
+ var networkOperator = ""
+ try {
+ val tel = context!!
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ networkOperator = tel.networkOperator
+ } catch (var2: Exception) {
+ }
+ return networkOperator
+ }
+
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getCellLocation(context: Context?): String {
+ var cellLocation: GsmCellLocation? = null
+ try {
+ val tel = context!!
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ cellLocation = tel.cellLocation as GsmCellLocation
+ } catch (var2: Exception) {
+ }
+ return cellLocation?.toString() ?: ""
+ }
+ @JvmStatic
+ fun getDefaultHost(context: Context?): String {
+ var proHost = ""
+ var proPort = 0
+ try {
+ proHost = Proxy.getDefaultHost()
+ proPort = Proxy.getDefaultPort()
+ } catch (var3: Exception) {
+ Log.i("","sss")
+ }
+ // return "$proHost $proPort"
+ return proHost +" "+proPort
+ }
+
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getVoiceMailNumber(context: Context?): String {
+ var voiceMailNumber = ""
+ try {
+ val tel = context!!.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ voiceMailNumber = tel.voiceMailNumber
+ } catch (var2: Exception) {
+ return ""
+ }
+ if(TextUtils.isEmpty( return voiceMailNumber)){
+ return ""
+ }else{
+ return voiceMailNumber
+ }
+ }
+}
+
diff --git a/mexicoDevices/src/main/java/com/ok/moxico/MxcNetTool.kt b/mexicoDevices/src/main/java/com/ok/moxico/MxcNetTool.kt
new file mode 100644
index 0000000..dacb0b1
--- /dev/null
+++ b/mexicoDevices/src/main/java/com/ok/moxico/MxcNetTool.kt
@@ -0,0 +1,443 @@
+package com.ok.moxico
+
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.NetworkInfo
+import android.net.wifi.WifiManager
+import android.os.Build.VERSION
+import android.telephony.TelephonyManager
+import android.text.TextUtils
+import android.text.format.Formatter
+import android.util.Log
+import androidx.annotation.RequiresPermission
+
+import java.net.*
+import java.util.*
+
+/**
+ * @author tamsiree
+ * @date 2016/1/29
+ */
+object MxcNetTool {
+ /**
+ * no network
+ */
+ const val NETWORK_NO = -1
+
+ /**
+ * wifi network
+ */
+ const val NETWORK_WIFI = 1
+
+ /**
+ * "2G" networks
+ */
+ const val NETWORK_2G = 2
+
+ /**
+ * "3G" networks
+ */
+ const val NETWORK_3G = 3
+
+ /**
+ * "4G" networks
+ */
+ const val NETWORK_4G = 4
+
+ /**
+ * unknown network
+ */
+ const val NETWORK_UNKNOWN = 5
+ private const val NETWORK_TYPE_GSM = 16
+ private const val NETWORK_TYPE_TD_SCDMA = 17
+ private const val NETWORK_TYPE_IWLAN = 18
+
+ /**
+ * 需添加权限
+ *
+ * @param context 上下文
+ * @return 网络类型
+ * @code
+ *
+ *
+ * 它主要负责的是
+ * 1 监视网络连接状态 包括(Wi-Fi, 2G, 3G, 4G)
+ * 2 当网络状态改变时发送广播通知
+ * 3 网络连接失败尝试连接其他网络
+ * 4 提供API,允许应用程序获取可用的网络状态
+ *
+ *
+ * netTyped 的结果
+ * @link #NETWORK_NO = -1; 当前无网络连接
+ * @link #NETWORK_WIFI = 1; wifi的情况下
+ * @link #NETWORK_2G = 2; 切换到2G环境下
+ * @link #NETWORK_3G = 3; 切换到3G环境下
+ * @link #NETWORK_4G = 4; 切换到4G环境下
+ * @link #NETWORK_UNKNOWN = 5; 未知网络
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getNetWorkType(context: Context): String {
+ // 获取ConnectivityManager
+ val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ val ni = cm.activeNetworkInfo // 获取当前网络状态
+ var netType = ""
+ if (ni != null && ni.isConnectedOrConnecting) {
+ when (ni.type) {
+ ConnectivityManager.TYPE_WIFI -> {
+ netType = "NETWORK_WIFI"
+ // RxToast.success("切换到wifi环境下")
+ }
+ ConnectivityManager.TYPE_MOBILE -> when (ni.subtype) {
+ NETWORK_TYPE_GSM, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_IDEN -> {
+ netType = "NETWORK_2G"
+ // RxToast.info("切换到2G环境下")
+ }
+ TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyManager.NETWORK_TYPE_HSPAP, NETWORK_TYPE_TD_SCDMA -> {
+ netType = "NETWORK_3G"
+ // RxToast.info("切换到3G环境下")
+ }
+ TelephonyManager.NETWORK_TYPE_LTE, NETWORK_TYPE_IWLAN -> {
+ netType = "NETWORK_4G"
+ // RxToast.info("切换到4G环境下")
+ }
+ TelephonyManager.NETWORK_TYPE_NR -> {
+ netType = "NETWORK_5G"
+ // RxToast.info("切换到4G环境下")
+ }
+ else -> {
+ val subtypeName = ni.subtypeName
+ netType = if (subtypeName.equals("TD-SCDMA", ignoreCase = true)
+ || subtypeName.equals("WCDMA", ignoreCase = true)
+ || subtypeName.equals("CDMA2000", ignoreCase = true)
+ ) {
+ "NETWORK_3G"
+ } else {
+ "NETWORK_UNKNOWN"
+ }
+ // RxToast.normal("未知网络")
+ }
+ }
+ else -> {
+ netType = "NETWORK_UNKNOWN"
+ // RxToast.normal("未知网络")
+ }
+ }
+ } else {
+ netType = "NETWORK_NO"
+ // RxToast.error(context, "当前无网络连接")?.show()
+ }
+ return netType
+ }
+
+
+ @RequiresPermission("android.permission.INTERNET")
+ @JvmStatic
+ fun getIPAddress(useIPv4: Boolean): String? {
+ try {
+ val nis =
+ NetworkInterface.getNetworkInterfaces()
+ val adds = LinkedList()
+ label64@ while (true) {
+ var ni: NetworkInterface
+ do {
+ do {
+ if (!nis.hasMoreElements()) {
+ val var9: Iterator<*> = adds.iterator()
+ while (var9.hasNext()) {
+ val add = var9.next() as InetAddress
+ if (!add.isLoopbackAddress) {
+ val hostAddress = add.hostAddress
+ val isIPv4 =
+ hostAddress.indexOf(58.toChar()) < 0
+ if (useIPv4) {
+ if (isIPv4) {
+ return hostAddress
+ }
+ } else if (!isIPv4) {
+ val index = hostAddress.indexOf(37.toChar())
+ return if (index < 0) hostAddress.toUpperCase() else hostAddress.substring(
+ 0,
+ index
+ ).toUpperCase()
+ }
+ }
+ }
+ break@label64
+ }
+ ni = nis.nextElement() as NetworkInterface
+ } while (!ni.isUp)
+ } while (ni.isLoopback)
+ val addresses: Enumeration<*> = ni.inetAddresses
+ while (addresses.hasMoreElements()) {
+ adds.addFirst(addresses.nextElement())
+ }
+ }
+ } catch (var8: SocketException) {
+ var8.printStackTrace()
+ }
+ return ""
+ }
+
+ @RequiresPermission("android.permission.ACCESS_WIFI_STATE")
+ @JvmStatic
+ fun getWifiInfo(context: Context,type:String): String? {
+ val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
+ return if (wm == null) {
+ ""
+ } else {
+ return if (type.equals("netmask")){
+ Formatter.formatIpAddress(wm.dhcpInfo.netmask)
+ }else if (type.equals("gateway")){
+ Formatter.formatIpAddress(wm.dhcpInfo.gateway)
+ }else if (type.equals("ipAddress")){
+ Formatter.formatIpAddress(wm.dhcpInfo.ipAddress)
+ }else {
+ Formatter.formatIpAddress(wm.dhcpInfo.serverAddress)
+ }
+ }
+ }
+
+ @JvmStatic
+ fun getBroadcastIpAddress(): String? {
+ try {
+ val nis =
+ NetworkInterface.getNetworkInterfaces()
+ LinkedList()
+ while (true) {
+ var ni: NetworkInterface
+ do {
+ do {
+ if (!nis.hasMoreElements()) {
+ return ""
+ }
+ ni = nis.nextElement() as NetworkInterface
+ } while (!ni.isUp)
+ } while (ni.isLoopback)
+ val ias =
+ ni.interfaceAddresses
+ var i = 0
+ val size = ias.size
+ while (i < size) {
+ val ia = ias[i] as InterfaceAddress
+ val broadcast = ia.broadcast
+ if (broadcast != null) {
+ return broadcast.hostAddress
+ }
+ ++i
+ }
+ }
+ } catch (var8: SocketException) {
+ var8.printStackTrace()
+ return ""
+ }
+ }
+
+ @RequiresPermission("android.permission.ACCESS_WIFI_STATE")
+ @JvmStatic
+ fun getSSID(context: Context): String? {
+ val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
+ return if (wm == null) {
+ ""
+ } else {
+ val wi = wm.connectionInfo
+ if (wi == null) {
+ ""
+ } else {
+ val ssid = wi.ssid
+ if (TextUtils.isEmpty(ssid)) {
+ ""
+ } else {
+ if (ssid.length > 2 && ssid[0] == '"' && ssid[ssid.length - 1] == '"') ssid.substring(
+ 1,
+ ssid.length - 1
+ ) else ssid
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 判断网络连接是否可用
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun isNetworkAvailable(context: Context): Boolean {
+ val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ if (cm == null) {
+ } else {
+ //如果仅仅是用来判断网络连接
+ //则可以使用 cm.getActiveNetworkInfo().isAvailable();
+ val info = cm.allNetworkInfo
+ if (info != null) {
+ for (i in info.indices) {
+ if (info[i].state == NetworkInfo.State.CONNECTED) {
+ return true
+ }
+ }
+ }
+ }
+ return false
+ }
+
+ /**
+ * 判断网络是否可用
+ * 需添加权限
+ *
+ * @code
+ */
+ @JvmStatic
+ fun isAvailable(context: Context): Boolean {
+ val info = getActiveNetworkInfo(context)
+ return info != null && info.isAvailable
+ }
+
+
+ @RequiresPermission("android.permission.INTERNET")
+ @JvmStatic
+ fun isAvailableByPing(): Boolean {
+ return isAvailableByPing("")
+ }
+
+ @RequiresPermission("android.permission.INTERNET")
+ fun isAvailableByPing(ip: String?): Boolean {
+ val realIp = if (TextUtils.isEmpty(ip)) "223.5.5.5" else ip!!
+ val result =
+ MxcAdbUtils.execCmd(
+ String.format(
+ "ping -c 1 %s",
+ realIp
+ ), false
+ )
+ return result.result == 0
+ }
+
+
+ @RequiresPermission("android.permission.INTERNET")
+ @JvmStatic
+ fun isAvailableByDns(): Boolean {
+ return isAvailableByDns("")
+ }
+
+ @RequiresPermission("android.permission.INTERNET")
+ fun isAvailableByDns(domain: String?): Boolean {
+ val realDomain = if (TextUtils.isEmpty(domain)) "www.baidu.com" else domain!!
+ return try {
+ val inetAddress = InetAddress.getByName(realDomain)
+ inetAddress != null
+ } catch (var4: UnknownHostException) {
+ var4.printStackTrace()
+ false
+ }
+ }
+
+
+ @RequiresPermission(allOf = ["android.permission.ACCESS_WIFI_STATE", "android.permission.INTERNET"])
+ @JvmStatic
+ fun isWifiAvailable(context: Context): Boolean {
+ return getWifiEnabled(context) && isAvailable(context)
+ }
+
+ @RequiresPermission("android.permission.ACCESS_WIFI_STATE")
+ fun getWifiEnabled(context: Context): Boolean {
+ val manager =
+ context.getSystemService(Context.WIFI_SERVICE) as WifiManager
+ return manager?.isWifiEnabled ?: false
+ }
+
+
+ /**
+ * 判断wifi是否连接状态
+ *
+ * 需添加权限 ``
+ *
+ * @param context 上下文
+ * @return `true`: 连接
`false`: 未连接
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun isWifiConnected(context: Context): Boolean {
+ val cm = context
+ .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ return cm != null && cm.activeNetworkInfo != null && cm.activeNetworkInfo!!.type == ConnectivityManager.TYPE_WIFI
+ }
+
+
+
+ /**
+ * 判断网络是否是4G
+ * 需添加权限
+ *
+ * @code
+ */
+ @JvmStatic
+ fun is4G(context: Context): Boolean {
+ val info = getActiveNetworkInfo(context)
+ return info != null && info.isAvailable && info.subtype == TelephonyManager.NETWORK_TYPE_LTE
+ }
+
+ @JvmStatic
+ fun is5G(context: Context): Boolean {
+ val info = getActiveNetworkInfo(context)
+ return info != null && info.isAvailable && info.subtype == TelephonyManager.NETWORK_TYPE_NR
+ }
+
+
+ /**
+ * 获取活动网络信息
+ *
+ * @param context 上下文
+ * @return NetworkInfo
+ */
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getActiveNetworkInfo(context: Context): NetworkInfo? {
+ try {
+ val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ return cm.activeNetworkInfo!!
+ }catch (e:Exception){
+ e.printStackTrace()
+ }
+ return null
+ }
+
+ @SuppressLint("MissingPermission")
+ @JvmStatic
+ fun getMobileDataEnabled(context: Context): Boolean {
+ try {
+ val tm = context
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ ?: return false
+ if (VERSION.SDK_INT >= 26) {
+ return tm.isDataEnabled
+ }
+ val getMobileDataEnabledMethod =
+ tm.javaClass.getDeclaredMethod("getDataEnabled")
+ if (null != getMobileDataEnabledMethod) {
+ return getMobileDataEnabledMethod.invoke(tm) as Boolean
+ }
+ } catch (var2: Exception) {
+ Log.e("NetworkUtils", "getMobileDataEnabled: ", var2)
+ }
+ return false
+ }
+ /**
+ * 获取移动网络运营商名称
+ *
+ * 如中国联通、中国移动、中国电信
+ *
+ * @param context 上下文
+ * @return 移动网络运营商名称
+ */
+ @JvmStatic
+ fun getNetworkOperatorName(context: Context): String? {
+ val tm = context
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+ return tm.networkOperatorName
+ }
+
+
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..44c548d
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,3 @@
+rootProject.name = "MexicoMaven"
+include ':app'
+include ':mexicoDevices'