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'