關於WiFiManager地說明可以參考 [Android] 用WifiManager來get wifi的SSID, power level和所使用的channel基本資訊。
本篇主要就Android M以及使用Android Studio為基礎,利用原本的範例當修改。
程式碼下載:GitHub
與原本差異如下:
1. 增加MVC的模型來撰寫程式碼
2. 增加permissions的控制處理
大致上與原本差不多,但主要要增加ACCESS_COARSE_LOCATION這個permission,否則Android M會拿到空的網路掃描結果(我是用Android 7.1.1當測試機)。
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
其他程式碼的部分
MainActivity.java
package com.cybernut.wifimanager.view;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import com.cybernut.wifimanager.common.RetainedFragmentManager;
import com.cybernut.wifimanager.controller.MainActivityOps;
import com.cybernut.wifimanager.R;
public class MainActivity extends AppCompatActivity {
/**
* Debugging tag used by the Android logger.
*/
private static final String TAG =
MainActivity.class.getSimpleName();
/**
* Used to retain the MainActivityOps state between runtime configuration
* changes.
*/
protected final RetainedFragmentManager mRetainedFragmentManager =
new RetainedFragmentManager(this.getFragmentManager(),
TAG);
private static final String MAIN_OPS_STATE = "MAIN_OPS_STATE";
private MainActivityOps mMainActivityOps;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleConfigurationChanges();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
mMainActivityOps.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
/**
* Handle hardware reconfigurations, such as rotating the display.
*/
protected void handleConfigurationChanges() {
// If this method returns true then this is the first time the
// Activity has been created.
if (mRetainedFragmentManager.firstTimeIn()) {
Log.d(TAG,
"First time onCreate() call");
// Create the MainActivityOps object one time.
mMainActivityOps = new MainActivityOps(this);
// Store the LoginOps into the RetainedFragmentManager.
mRetainedFragmentManager.put(MAIN_OPS_STATE,
mMainActivityOps);
} else {
// The RetainedFragmentManager was previously initialized,
// which means that a runtime configuration change
// occurred.
Log.d(TAG,
"Second or subsequent onCreate() call");
// Obtain the LoginOps object from the
// RetainedFragmentManager.
mMainActivityOps =
mRetainedFragmentManager.get(MAIN_OPS_STATE);
// This check shouldn't be necessary under normal
// circumstances, but it's better to lose state than to
// crash!
if (mMainActivityOps == null) {
// Create the MainActivityOps object one time.
mMainActivityOps = new MainActivityOps(this);
// Store the LoginOps into the RetainedFragmentManager.
mRetainedFragmentManager.put(MAIN_OPS_STATE,
mMainActivityOps);
} else
// Inform it that the runtime configuration change has
// completed.
mMainActivityOps.onConfigurationChange(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mMainActivityOps.unregisterReceiverAndDestroy();
}
}
MainActivityOps.java
package com.cybernut.wifimanager.controller;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import com.cybernut.wifimanager.R;
import com.cybernut.wifimanager.model.WiFiList;
import com.cybernut.wifimanager.view.MainActivity;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
public class MainActivityOps {
/**
* Debugging tag used by the Android logger.
*/
private static final String TAG =
MainActivityOps.class.getSimpleName();
private WifiManager wifiManager;
private int size = 0;
private List results;
private ArrayList> mArrayList = new ArrayList<>();
private SimpleAdapter mAdapter;
private BroadcastReceiver mBroadcastReceiver;
/**
* Used to enable garbage collection.
*/
private WeakReference mMainActivity;
private WeakReference mFab;
private WeakReference mTextView;
/**
* Id to identity ACCESS_COARSE_LOCATION permission request.
*/
private static final int REQUEST_ACCESS_LOCATION = 101;
public MainActivityOps(MainActivity mainActivity) {
// Initialize the WeakReference.
mMainActivity = new WeakReference<>(mainActivity);
// Finish the initialization steps.
initializeViewFields();
initializeNonViewFields();
}
private void initializeViewFields() {
Log.d(TAG, "initializeViewFields");
// Get references to the UI components.
mMainActivity.get().setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) mMainActivity.get().findViewById(R.id.toolbar);
mMainActivity.get().setSupportActionBar(toolbar);
mTextView = new WeakReference<>
((TextView) mMainActivity.get().findViewById(R.id.textView2));
WeakReference mListView = new WeakReference<>
((ListView) mMainActivity.get().findViewById(R.id.listView1));
populateAutoComplete();
wifiManager = (WifiManager) mMainActivity.get().getSystemService(Context.WIFI_SERVICE);
mAdapter = new SimpleAdapter(mMainActivity.get(), mArrayList, R.layout.list_wifi,
new String[] {"ssid", "power", "freq"}, new int[] {R.id.ssid, R.id.power, R.id.freq});
mListView.get().setAdapter(mAdapter);
mFab = new WeakReference<>
((FloatingActionButton) mMainActivity.get().findViewById(R.id.fab));
mFab.get().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
wifiManager.startScan();
Snackbar.make(view, "Scanning...", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
if(!wifiManager.isWifiEnabled())
{
AlertDialog.Builder dialog = new AlertDialog.Builder(mMainActivity.get());
dialog.setTitle("Remind");
dialog.setMessage("Your Wi-Fi is disabled, enable it?");
dialog.setIcon(android.R.drawable.ic_dialog_info);
dialog.setCancelable(false);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
wifiManager.setWifiEnabled(true);
Snackbar.make(mFab.get(),
"WiFi is disabled... making it enabled", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
dialog.show();
}
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
results = wifiManager.getScanResults();
size = results.size();
Log.d(TAG, "Acquire wifi "+size);
mArrayList.clear();
for(int i=0; i item = new HashMap<>();
item.put("ssid", results.get(i).SSID);
item.put("power", results.get(i).level+" dBm");
String wifichn = WiFiList.WIFI_CHANNELS.containsKey(
Integer.toString(results.get(i).frequency))?
WiFiList.WIFI_CHANNELS.
get(Integer.toString(results.get(i).frequency)):"5G";
item.put("freq", wifichn);
mArrayList.add(item);
}
// Sort by power
Collections.sort(mArrayList, new Comparator>() {
@Override
public int compare(HashMap lhs,
HashMap rhs) {
// TODO Auto-generated method stub
return (lhs.get("power")).compareTo(rhs.get("power"));
}
});
if(size > 0) {
mTextView.get().setText(mArrayList.get(0).get("ssid"));
}
mAdapter.notifyDataSetChanged();
}
};
mMainActivity.get().registerReceiver(mBroadcastReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
if(size > 0) {
mTextView.get().setText(mArrayList.get(0).get("ssid"));
}
}
/**
* (Re)initialize the non-view fields (e.g.,
* GenericServiceConnection objects).
*/
private void initializeNonViewFields() {
Log.d(TAG, "initializeNonViewFields");
}
private void populateAutoComplete() {
if (!mayRequestLocation()) {
return;
}
}
private boolean mayRequestLocation() {
Log.d(TAG, "mayRequestLocation");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
Log.d(TAG, "newer than M");
if (mMainActivity.get().checkSelfPermission(ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
Log.d(TAG, "no permission");
if (mMainActivity.get().
shouldShowRequestPermissionRationale(ACCESS_COARSE_LOCATION)) {
Log.d(TAG, "request permission");
Snackbar.make(mFab.get(),
R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
mMainActivity.get().
requestPermissions(new String[]{
ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_LOCATION);
}
});
} else {
Log.d(TAG, "Permission OK");
mMainActivity.get().
requestPermissions(new String[]{
ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_LOCATION);
}
return false;
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult");
if (requestCode == REQUEST_ACCESS_LOCATION) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
populateAutoComplete();
}
}
}
/**
* Called after a runtime configuration change occurs to finish
* the initialization steps.
*/
public void onConfigurationChange(MainActivity mainActivity) {
Log.d(TAG,
"onConfigurationChange() called");
// Reset the mActivity WeakReference.
mMainActivity = new WeakReference<>(mainActivity);
// (Re)initialize all the View fields.
initializeViewFields();
}
public void unregisterReceiverAndDestroy() {
Log.d(TAG, "go to unregisterReceiverAndDestroy");
if(mBroadcastReceiver!=null) {
mMainActivity.get().unregisterReceiver(mBroadcastReceiver);
mBroadcastReceiver = null;
}
}
}
Layout設定
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.cybernut.wifimanager.view.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_info" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.cybernut.wifimanager.view.MainActivity"
tools:showIn="@layout/activity_main">
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_marginTop="46dp"
android:background="#ff8" >
</ListView>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/wifi_ssid" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/wifi_analysis"
android:layout_below="@+id/textView1"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
list_wifi.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/ssid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="TextView" />
<TextView
android:id="@+id/power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/ssid"
android:layout_below="@+id/ssid"
android:text="TextView" />
<TextView
android:id="@+id/freq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/power"
android:layout_alignBottom="@+id/power"
android:layout_centerHorizontal="true"
android:text="TextView" />
</RelativeLayout>
執行結果
Android 7.1.1 API 25, Nexus 5X
Android 4.1.1 API 16, HTC J
利用這樣就可以簡單取得WiFi的資訊。
沒有留言:
張貼留言