You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

593 lines
23 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.xypower.mpremote;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiNetworkSuggestion;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import com.xypower.mpremote.databinding.ActivityMainBinding;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
// Used to load the 'mpremote' library on application startup.
static {
System.loadLibrary("mpremote");
}
private static final String TAG = "ADB";
private static final boolean DEBUG = true;
public static final int RSSI_LEVELS = 5;
private static final String DEFAULT_PRE_SHARED_KEY = SettingsActivity.DEFAULT_PRE_SHARED_KEY;
private static final int REQUEST_CODE_PERMISSIONS = 1025;
private static final int REQUEST_CODE_SETTINGS = SettingsActivity.REQUEST_CODE_SETTINGS;
private static final String WIFI_IP_PREFIX = "192.168.";
// private static final String WIFI_IP_DEVIDE = "192.168.50.1";
private static final String WIFI_IP_DEVICE = "192.168.50.137";
private ActivityMainBinding binding;
private Handler mHandler;
private List<ScanResult> mScanResults = new ArrayList<>();
private ScanResult mCurrentScanResult;
private String mPassword = DEFAULT_PRE_SHARED_KEY;
private WifiAdaper mAdapter;
private List<Map<String, Object>> mItems = new ArrayList<Map<String, Object>>();
private ConnectivityManager mConnectivityManager;
private NetworkConnectChangedReceiver mNetworkConnectChangedReceiver;
private ConnectivityManager.NetworkCallback mNetworkCallback;
public class WifiAdaper extends SimpleAdapter{
public WifiAdaper(Context context, List<Map<String, Object>> items, int resource, String[] from, int[] to) {
super(context, items, resource, from, to);
}
public View getView(int position, View convertView, ViewGroup parent){
convertView = super.getView(position, convertView, parent);
TextView textView = (TextView)convertView.findViewById(R.id.id_text);
ScanResult scanResult = mScanResults.get(position);
// if (scanResult.)
String text = (String)mItems.get(position).get("text");
if (text.startsWith("XY") || text.startsWith("xy")) {
textView.setTextColor(Color.RED);
textView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
} else {
textView.setTextColor(Color.BLACK);
textView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
}
return convertView;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
loadSettings();
mHandler = new Handler();
mConnectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
binding.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
mCurrentScanResult = mScanResults.get(position);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String s1 = normalizeSSID(mCurrentScanResult.SSID);
String s2 = normalizeSSID(wifiInfo.getSSID());
if (TextUtils.equals(s1, s2)) {
openDeviceActivity();
} else {
startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS));
}
// connectWifi(mCurrentScanResult.SSID, mCurrentScanResult.BSSID, mPassword);
}
});
if (applyForPermissions()) {
scanWifi();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mConnectivityManager != null && mNetworkCallback != null) {
mConnectivityManager.bindProcessToNetwork(null);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//当点击不同的menu item 是执行不同的操作
switch (id) {
case R.id.action_refresh:
scanWifi();
break;
case R.id.action_settings: {
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
startActivityForResult(intent, REQUEST_CODE_SETTINGS);
}
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
try {
ArrayList<String> requestList = new ArrayList<>();//允许询问列表
ArrayList<String> banList = new ArrayList<>();//禁止列表
for(int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG,"【"+permissions[i]+"】权限授权成功");
} else {
//判断是否允许重新申请该权限
boolean nRet = ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[i]);
Log.i(TAG,"shouldShowRequestPermissionRationale nRet="+nRet);
if (nRet) {//允许重新申请
requestList.add(permissions[i]);
} else {//禁止申请
banList.add(permissions[i]);
}
}
}
//优先对禁止列表进行判断
if (banList.size() > 0) {
//告知该权限作用,要求手动授予权限
showFinishedDialog();
}
else if (requestList.size() > 0) {
//告知权限的作用,并重新申请
showTipDialog(requestList);
} else {
// showToast("权限授权成功");
scanWifi();
}
} catch (Exception e) {
e.printStackTrace();
// showToast("权限申请回调中发生异常");
}
}
public void showFinishedDialog() {
AlertDialog dialog = new AlertDialog.Builder(getApplicationContext())
.setTitle("警告")
.setMessage("请前往设置中打开相关权限,否则功能无法正常运行!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 一般情况下如果用户不授权的话,功能是无法运行的,做退出处理
finish();
}
})
.create();
dialog.show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SETTINGS) {
loadSettings();
}
}
public void showTipDialog(ArrayList<String> pmList){
AlertDialog dialog = new AlertDialog.Builder(getApplicationContext())
.setTitle("提示")
.setMessage("【"+pmList.toString()+"】权限为应用必要权限,请授权")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String[] sList=pmList.toArray(new String[0]);
//重新申请该权限
ActivityCompat.requestPermissions(MainActivity.this, sList, REQUEST_CODE_PERMISSIONS);
}
})
.create();
dialog.show();
}
protected void scanWifi() {
mScanResults.clear();
(new Thread(new Runnable() {
@Override
public void run() {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan();
List<ScanResult> scanResults = wifiManager.getScanResults();
Map<String, String> ssids = new HashMap<>();
for (ScanResult scanResult : scanResults) {
if (TextUtils.isEmpty(scanResult.SSID)) {
continue;
}
if (ssids.containsKey(scanResult.SSID)) {
continue;
}
ssids.put(scanResult.SSID, scanResult.SSID);
mScanResults.add(scanResult);
}
// mAdapter = new ArrayAdapter<>()
mHandler.post(new Runnable() {
@Override
public void run() {
refreshListView();
}
});
}
})).start();
}
private void connectWifi(String ssid, String bssid, String pwd) {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// Android 10
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
WifiNetworkSuggestion suggestion =
new WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setWpa2Passphrase((pwd))
.setIsAppInteractionRequired(true)
.build();
List<WifiNetworkSuggestion> suggestionsList = new ArrayList<>();
suggestionsList.add(suggestion);
wifiManager.removeNetworkSuggestions(suggestionsList);
int status = wifiManager.addNetworkSuggestions(suggestionsList);
// step2
if ((status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) || (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE)) {
WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(pwd)
.build();
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build();
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull Network network) {
super.onAvailable(network);
NetworkInfo networkInfo = mConnectivityManager.getNetworkInfo(network);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String s1 = normalizeSSID(wifiInfo.getSSID());
String s2 = normalizeSSID(mCurrentScanResult.SSID);
if (TextUtils.equals(s1, s2)) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// requires android.permission.INTERNET
mConnectivityManager.bindProcessToNetwork(network);
openDeviceActivity();
}
});
}
}
@Override
public void onUnavailable() {
super.onUnavailable();
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectivityManager.bindProcessToNetwork(null);
}
});
}
};
mConnectivityManager.requestNetwork(request, mNetworkCallback);
} else {
}
} else {
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + ssid + "\"";
wifiConfiguration.BSSID = "\"" + bssid + "\"";
wifiConfiguration.preSharedKey = "\"" + pwd + "\"";
int nerworkId = wifiManager.addNetwork(wifiConfiguration);
try {
wifiManager.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
/*
if (mNetworkConnectChangedReceiver != null) {
unregisterReceiver(mNetworkConnectChangedReceiver);
mNetworkConnectChangedReceiver = null;
registerNetworkConnectChangeReceiver();
}
*/
wifiManager.enableNetwork(nerworkId, true);
wifiManager.reconnect();
}
}
private void refreshListView() {
mAdapter = new WifiAdaper(this, getData(), R.layout.list_item, new String[] { "img", "text" },
new int[] { R.id.id_img, R.id.id_text });
binding.listView.setAdapter(mAdapter);
}
private List<Map<String, Object>> getData() {
mItems.clear();
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = "";
if (wifiInfo != null) {
ssid = wifiInfo.getSSID();
if (!TextUtils.isEmpty(ssid)) {
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
ssid = ssid.substring(1, ssid.length() - 1);
}
}
}
for (ScanResult scanResult : mScanResults) {
Map map = new HashMap<String, Object>();
int signalLevel = WifiManager.calculateSignalLevel(scanResult.level, RSSI_LEVELS);
int drawableId = R.drawable.ic_wifi_signal_0;
boolean connected = TextUtils.equals(ssid, scanResult.SSID);
switch (signalLevel) {
case 1:
drawableId = connected ? R.drawable.ic_wifi_signal_1_green : R.drawable.ic_wifi_signal_1;
break;
case 2:
drawableId = connected ? R.drawable.ic_wifi_signal_2_green : R.drawable.ic_wifi_signal_2;
break;
case 3:
drawableId = connected ? R.drawable.ic_wifi_signal_3_green : R.drawable.ic_wifi_signal_3;
break;
case 4:
drawableId = connected ? R.drawable.ic_wifi_signal_4_green : R.drawable.ic_wifi_signal_4;
break;
default:
drawableId = connected ? R.drawable.ic_wifi_signal_0_green : R.drawable.ic_wifi_signal_0;
break;
}
map.put("img", drawableId);
// if (scanR)
map.put("text", scanResult.SSID);
mItems.add(map);
}
return mItems;
}
class NetworkConnectChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
// 这个监听wifi的连接状态即是否连上了一个有效无线路由当上边广播的状态是WifiManager.WIFI_STATE_DISABLING和WIFI_STATE_DISABLED的时候根本不会接到这个广播。
// 在上边广播接到广播是WifiManager.WIFI_STATE_ENABLED状态的同时也会接到这个广播当然刚打开wifi肯定还没有连接到有效的无线
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
String bssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
if (null == parcelableExtra) {
return;
}
if (mCurrentScanResult != null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
NetworkInfo.State state = networkInfo.getState();
// Log.e("NetWork Sate Change:"+state+" connectedBssid:" + connectedBssid);
if(state == NetworkInfo.State.CONNECTED) {
String ssid = wifiInfo.getSSID();
String addSSID = mCurrentScanResult.SSID;
if (!(mCurrentScanResult.SSID.startsWith("\"") && mCurrentScanResult.SSID.endsWith("\""))) {
addSSID = "\"" + addSSID + "\"";
}
// Log.i(ssid + "***>" + mCurrentScanResult.SSID);
// Log.i("总共耗时:"+((System.currentTimeMillis()-start)/1000.0));
if (ssid.equals(addSSID)) {
unregisterReceiver(mNetworkConnectChangedReceiver);
mNetworkConnectChangedReceiver = null;
}
}
}
}
}
private void registerNetworkConnectChangeReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mNetworkConnectChangedReceiver = new NetworkConnectChangedReceiver();
registerReceiver(mNetworkConnectChangedReceiver, filter);
}
public boolean applyForPermissions() {
String[] PM_MULTIPLE = {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CHANGE_NETWORK_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.ACCESS_FINE_LOCATION
};
try {
ArrayList<String> pmList = new ArrayList<>();
//获取当前未授权的权限列表
for(String permission:PM_MULTIPLE) {
int nRet = ContextCompat.checkSelfPermission(this,permission);
if(nRet != PackageManager.PERMISSION_GRANTED) {
pmList.add(permission);
}
}
if (pmList.size() > 0) {
// Log.i(TAG,"进行权限申请...");
String[] sList = pmList.toArray(new String[0]);
ActivityCompat.requestPermissions(this, sList,REQUEST_CODE_PERMISSIONS);
return false;
}
} catch(Exception e){
e.printStackTrace();
}
return true;
}
protected void loadSettings() {
SharedPreferences preferences = getSharedPreferences("mpremote", MODE_PRIVATE);
mPassword = preferences.getString("password", DEFAULT_PRE_SHARED_KEY);
}
protected void openDeviceActivity() {
String ipAddressByWifi = null;
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
ipAddressByWifi = Formatter.formatIpAddress(wifiManager.getDhcpInfo().ipAddress);
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
if (ipAddressByWifi.contains(WIFI_IP_PREFIX)) {
String deviceIP = Formatter.formatIpAddress(wifiManager.getDhcpInfo().gateway);
if (DEBUG) {
deviceIP = WIFI_IP_DEVICE;
}
Intent intent = new Intent(MainActivity.this, DeviceActivity.class);
// intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("deviceIp", deviceIP);
intent.putExtra("SSID", mCurrentScanResult.SSID);
startActivity(intent);
}
}
}
private String normalizeSSID(String ssid) {
if (TextUtils.isEmpty(ssid)) {
return ssid;
}
if (!(ssid.startsWith("\"") && ssid.endsWith("\""))) {
return "\"" + ssid + "\"";
}
return ssid;
}
/**
* A native method that is implemented by the 'mpremote' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}