Android設備應該經過何種方式,才能枚舉局域網內的全部主機(這裏的主機主要是指Android設備):html
在雙方沒協議的狀況下 試試循環Runtime.getRuntime().exec("ping "+ip+"-i 1 -c 2");java
ping每一個IPandroid
Runtime.getRuntime().exec("arp -a >"+savefile);網絡
再去處理savefile這個文件多線程
另外就是發送udp廣播了,請求方將自身ip和命令廣播出去,設備收到命令將自身ip用tcp/udp發送給請求方。app
每一個設備要創建Socket監聽廣播才能夠。 異步
經過google提供的WifiManager類,我已經能夠獲取當前設備的IP,網關,和子網掩碼。socket
這樣的話,我已經能夠計算出,當前局域網內全部可能的IP地址。tcp
目前關於如何獲知局域網內的其餘設備,我有兩個方案:ide
1.UDP廣播,AP在運行的過程當中,不停的發送UDP廣播(例如每一秒鐘一次),
而後接收端每10秒檢查一次收到的廣播包,若是發現過去的10秒鐘內接受到過某個IP發送的廣播包,
則認爲這個IP所在的機器上正在運行個人AP(簡單的來講,就是這個機器在線),接收端能夠和它通訊。
考慮到網絡的丟包率的話,能夠提升發送端的發送頻率或者增大接收端的掃描間隔,來提升可靠性。
2.使用TCP輪詢。
經過本機IP和子網掩碼,計算本子網內全部可能的IP地址,輪詢這些IP地址,
嘗試Socket.connect(SocketAddress remoteAddr, int timeout)來進行鏈接,能連上則認爲機器在線。超時則判斷機器離線。
不過,這種狀況下,timeout的值設置得小的話,則在網絡狀況不佳(就以咱們公司的wifi網絡爲例),容易遺漏設備,
timeout值設置過大,則輪詢花費的時間太多。
TCP的好處在於丟包的問題得以解決,可是輪詢太費時間,利用多線程的話,的確能夠縮短輪詢時間,可是形成的負荷又太大。
MulticastSocket
正常應該是你在手機端建立一個UDP的接收線程,而後又一個多播,多播發出去後,在多播端收到消息(消息裏包含發多播的ip)後,
給發送端發送一個udp消息(消息裏包含本身的ip信息) 而後手機端的UDP線程接收到對方發過來的消息後就能夠顯示出來了
一、一種是本身寫軟件,相似飛鴿傳書,本身進行UDP廣播監聽,就能夠找到。
二、若是想用相似網上鄰居那種,搜索下關於nsd(網絡發現服務)的東西,這塊沒作過。具體的東西在android.net.nsd包下邊。
public class WifiDemoActivity extends Activity {
private Button mTestButton;
private WifiManager mWifiManager;
private TextView iptextview;
static int threadCount = 0;
boolean isOver = false;
static int pingSize = 0;
public ArrayList<Map<String, Object>> ping; // ping 後的結果集
private ListView showiplistview;
public ArrayList<Map<String, Object>> getPing() { // 用來獲得ping後的結果集
return ping;
}
public void setPing(ArrayList<Map<String, Object>> ping){
this.ping=ping;
}
@Override
protected void onPause() {
System.exit(0);
finish();
super.onPause();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ping = new ArrayList<Map<String, Object>>();
iptextview = (TextView) findViewById(R.id.IPTEXTVIEWID);
mTestButton = (Button) findViewById(R.id.button1);
showiplistview = (ListView) findViewById(R.id.SHOWIPLISTVIEWID);
mTestButton.setOnClickListener(mAllClickListener);
mWifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
}
@Override
protected void onResume() {
isOver = true;
mUpdaHandler.sendMessage(createMessage(10003, null));
super.onResume();
}
private View.OnClickListener mAllClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
if (ping.size() > 0) {
ping.clear();
((IpAdapter) showiplistview.getAdapter()).setIpData(ping);
}
new Thread() {
public void run() {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
mWifiManager.getConfiguredNetworks();
List<WifiConfiguration> list = mWifiManager.getConfiguredNetworks();
for (WifiConfiguration wifiConfiguration : list) {
String ssid = wifiConfiguration.SSID;
String mSsid = ssid.substring(1, ssid.length() - 1);
String result = wifiConfiguration.toString();
if (mSsid.equalsIgnoreCase(wifiInfo.getSSID())) {
Log.d("Tag", wifiConfiguration.toString());
try {
int i = result.indexOf("LinkAddresses");
int i1 = result.indexOf("Routes");
String ipAddress = result.substring(i, i1).trim().substring(16,result.substring(i, i1).length() - 6);
Log.d("Tag", ipAddress);
int i2 = result.indexOf("DnsAddresses");
String mWifiIntAddress = result.substring(i2).trim().substring(15,result.substring(i2).length() - 4);
Log.d("Tag", "WifiInetAddresses "+ mWifiIntAddress);
String[] s = { mWifiIntAddress, ipAddress };
mUpdaHandler.sendMessage(createMessage(10002, s));
PingAll(mWifiIntAddress);
} catch (Exception e) {
Log.e("Tag", "erro" + e);
}
}
}
}
}.start();
break;
default:
break;
}
}
};
public void PingAll(String hostAddress) {
// 首先獲得本機的IP,獲得網段
try {
int k = 0;
k = hostAddress.lastIndexOf(".");
String ss = hostAddress.substring(0, k + 1);
for (int i = 1; i <= 250; i++) { // 對全部局域網Ip
String iip = ss + i;
creatLog(WifiDemoActivity.class, "PingAll", iip, null);
Ping(iip);
}
// 等着全部Ping結束
while (isOver) {
Thread.sleep(3000);
if (threadCount == 0) {
isOver = false;
int k1 = 0;
String result="";
result=(String)ping.get(0).get("ip");
k1=result.lastIndexOf(".");
result=result.substring(k1+1,result.length());
int mResult=Integer.valueOf(result);
for(Map<String, Object> map:ping){
String s=(String) map.get("ip");
String s1= s.substring(k1+1,s.length());
int mS1=Integer.valueOf(s1);
mResult=mResult>mS1?mResult:mS1;
}
Log.d("Tag", ""+mResult);
mUpdaHandler.sendMessage(createMessage(10003, null));
}
creatLog(WifiDemoActivity.class, "pingall", "wait......", null);
}
} catch (Exception e) {
creatLog(WifiDemoActivity.class, "pingAll", "", e);
}
}
public void Ping(String ip) {
// 最多30個線程
try {
while (threadCount > 30) {
Thread.sleep(2);
}
creatLog(WifiDemoActivity.class, "ping", threadCount + "", null);
threadCount += 1;
runPingIPprocess(ip);
} catch (Exception e) {
creatLog(WifiDemoActivity.class, "ping", null, e);
}
}
public void runPingIPprocess(final String ipString) {
final Thread pingThread = new Thread() {
@Override
public void run() {
try {
//ping ip地址
Process p = Runtime.getRuntime().exec("ping -c 1 -w 5 " + ipString);
int status = p.waitFor();
if (status == 0) {
Map<String, Object> map = new HashMap<String, Object>();
creatLog(WifiDemoActivity.class, "runpingIpProcesses","true" + ipString, null);
map.put("ip", ipString);
ping.add(map);
pingSize++;
if (pingSize > 10) {
pingSize = 0;
//setPing(ping);
mUpdaHandler.sendMessage(createMessage(10001, ping));
Log.d("Tag", "you are number");
}
creatLog(WifiDemoActivity.class, "run",
ping.toString(), null);
} else {
creatLog(WifiDemoActivity.class, "runpingIPprocess","false", null);
}
threadCount--;
creatLog(WifiDemoActivity.class, "run now ",threadCount + "", null);
} catch (Exception e) {
threadCount--;
creatLog(WifiDemoActivity.class, "runPingIpprocess", null,e);
} finally {
}
}
};
pingThread.start();
}
private Handler mUpdaHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
IpAdapter adapter ;
switch (msg.what) {
case 10001:
try {
Log.d("Tag", ping.toString() + "over");
ArrayList<Map<String, Object>> pings = (ArrayList<Map<String, Object>>) msg.obj;
adapter = (IpAdapter) showiplistview.getAdapter();
adapter.setIpData(getPing());
creatLog(WifiDemoActivity.class, "10001", pings + "", null);
adapter.notifyDataSetChanged();
isOver=true;
} catch (Exception e) {
creatLog(WifiDemoActivity.class, "1001", null, e);
}
break;
case 10002:
String[] s = (String[]) msg.obj;
iptextview.setText("本機IP:" + s[1] + "\n路由器IP:" + s[0]);
break;
case 10003:
adapter = new IpAdapter(WifiDemoActivity.this, ping);
showiplistview.setAdapter(adapter);
break;
default:
break;
}
}
};
public static Message createMessage(int what, Object object) {
Message message = new Message();
message.what = what;
message.obj = object;
return message;
}
public static void creatLog(Class class1, String where, String data,
Exception e) {
if (e != null) {
Log.e(class1.getSimpleName() + " "+where, "erro \n" + e);
} else if (e == null) {
Log.d(class1.getSimpleName() + " "+where + "", data + "");
}
}
}
深刻學習:如何實現不一樣Android設備之間相同應用程序的網絡服務發現功能 .
在咱們的app中添加網絡服務發現功能(NSD)以方便在不一樣的設備上響應局域網中的請求。
這種功能對於多設備之間點對點服務來講頗有用,例如多人遊戲,多人通話,文件共享等。
一,在網絡中註冊你的服務
注意:這一步是可選操做,若是你對經過局域網廣播你的應用服務不關心,這一步大可省去。
在局域網中註冊你的服務,首先須要建立一個NsdServiceInfo對象。這個對象封裝了局域網內其餘設備鏈接你的服務的信息。
public void registerService(int port){
// Create the NsdServiceInfo object, and populate it.
NsdServiceInfo serviceInfo = newNsdServiceInfo();
// The name is subject to change based on conflicts
// with other services advertised on the same network.
serviceInfo.setServiceName("NsdChat");
serviceInfo.setServiceType("_http._tcp.");
serviceInfo.setPort(port);
....
}
這個代碼片斷設置了服務的名稱爲「NsdChat」。
這個名字在網絡中是可見的,它使用NSD來搜索局域網內的服務。
此外,須要注意的是這個名字在局域網中必定是惟一的,若是衝突的話也不用擔憂,由於Android會自動處理這種衝突。
例如若是在同一個局域網中的兩個設備都安裝了具有NsdChat服務的應用程序,其中一個應用程序會自動修改服務的名稱,如」NsdChat(2)「。
此外這個代碼片斷也設置了服務的類型,以定義應用程序所使用的傳輸層和傳輸協議。
具體語法規則中爲」_<protocol>._<transportlayer>".在代碼片斷中使用HTTP協議和TCP傳輸控制協議。
若是一個應用程序提供了打印服務就須要設置服務類型爲"_ipp._tcp"。
爲了便於集中管理,互聯網名稱和數字地址分配機構制定了一些權威的服務發現協議標準,其中包括NSD和Bonjour。
在爲你的服務設置端口的時候,應該避免與其餘應用程序產生衝突。
若是你正在使用套接字,下面的代碼片斷能夠告訴你如何簡單地初始化一個套接字 :
public void initializeServerSocket(){
// Initialize a server socket on the next available port.
mServerSocket = newServerSocket(0);
// Store the chosen port.
mLocalPort = mServerSocket.getLocalPort();
...
}
如今你能夠定義一個NsdServiceInfo對象了。
此時你須要實現RegistrationListener接口。
這個接口包涵了一些回調函數,這些回調函數用來警告你的應用程序是否可以成功註冊你的服務,或者告訴你是否可以成功取消註冊服務。
public void initializeRegistrationListener(){
mRegistrationListener = new NsdManager.RegistrationListener(){
@Override
public void onServiceRegistered(NsdServiceInfoNsdServiceInfo){
// Save the service name. Android may have changed it in order to
// resolve a conflict, so update the name you initially requested
// with the name Android actually used.
mServiceName = NsdServiceInfo.getServiceName();
}
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo,int errorCode){
// Registration failed! Put debugging code here to determine why.
}
@Override
public void onServiceUnregistered(NsdServiceInfo arg0){
// Service has been unregistered. This only happens when you call
// NsdManager.unregisterService() and pass in this listener.
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo,int errorCode){
// Unregistration failed. Put debugging code here to determine why.
}
};
}
二,在網絡中發現你的服務
在網絡中發現咱們的服務,就須要咱們的應用程序時刻監聽網絡中可用的服務廣播而且進行過濾。
服務發現,就像註冊服務同樣分兩步,第一設置一個搜索服務的監聽器和與之相關的回調函數,而且建立一個異步的方法discoverServices()。
public void initializeDiscoveryListener(){
// Instantiate a new DiscoveryListener
mDiscoveryListener = newNsdManager.DiscoveryListener(){
// Called as soon as service discovery begins.
@Override
public void onDiscoveryStarted(String regType){
Log.d(TAG,"Service discovery started");
}
@Override
public void onServiceFound(NsdServiceInfo service){
// A service was found! Do something with it.
Log.d(TAG,"Service discovery success"+ service);
if (!service.getServiceType().equals(SERVICE_TYPE)){
// Service type is the string containing the protocol and
// transport layer for this service.
Log.d(TAG,"Unknown Service Type: "+ service.getServiceType());
} elseif(service.getServiceName().equals(mServiceName)){
// The name of the service tells the user what they'd be
// connecting to. It could be "Bob's Chat App".
Log.d(TAG,"Same machine: "+ mServiceName);
} elseif(service.getServiceName().contains("NsdChat")){
mNsdManager.resolveService(service, mResolveListener);
}
}
@Override
public void onServiceLost(NsdServiceInfo service){
// When the network service is no longer available.
// Internal bookkeeping code goes here.
Log.e(TAG,"service lost"+ service);
}
@Override
public void onDiscoveryStopped(String serviceType){
Log.i(TAG,"Discovery stopped: "+ serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType,int errorCode){
Log.e(TAG,"Discovery failed: Error code:"+ errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType,int errorCode){
Log.e(TAG,"Discovery failed: Error code:"+ errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
}
NSD的API使用這個接口中的回調函數來同志你的應用程序什麼時候開始你的發現服務,合適你的發現服務失敗,合適你的發現服務對其餘應用程序可見或者不可見。
從上面的代碼片段中咱們能夠看到,當你的服務被發現的時候會作出一系列的檢查操做:
1.檢查搜索到的服務名稱是否時本身發出的
2.檢查搜索到的服務類型是不是可鏈接的
3.檢查服務名稱是否能夠被正確的應用程序成功的驗證鏈接。
設置好監聽器後,調用discoverServices()方法
mNsdManager.discoverServices(SERVICE_TYPE,NsdManager.PROTOCOL_NSD_SD,mDsicoveryListener);
三,在服務中鏈接你的服務
當你的應用程序在網絡中發現了一個可鏈接的服務的時候,
首先使用resolveService()方法肯定可鏈接服務的信息,
實現NsdManager.ResolverListener接口,
而且從NsdServiceInfo中獲得其中所封裝的消息。
public void initializeResolveListener(){
mResolveListener = newNsdManager.ResolveListener(){
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo,int errorCode){
// Called when the resolve fails. Use the error code to debug.
Log.e(TAG,"Resolve failed"+ errorCode);
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo){
Log.e(TAG,"Resolve Succeeded. "+ serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)){
Log.d(TAG,"Same IP.");
return;
}
mService = serviceInfo;
int port = mService.getPort();
InetAddress host = mService.getHost();
}
};
}
四,應用程序關閉時應取消註冊的服務
//In your application's Activity
@Override
protected void onPause(){
if (mNsdHelper!= null){
mNsdHelper.tearDown();
}
super.onPause();
}
@Override
protected void onResume(){
super.onResume();
if (mNsdHelper!= null){
mNsdHelper.registerService(mConnection.getLocalPort());
mNsdHelper.discoverServices();
}
}
@Override
protected void onDestroy(){
mNsdHelper.tearDown();
mConnection.tearDown();
super.onDestroy();
}
// NsdHelper's tearDown method
public void tearDown(){
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
代碼
package com.wifitest;
import java.util.List;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
public class WifiManageClass {
private WifiManager wifiManager;// 聲明管理對象
private WifiInfo wifiInfo;// Wifi信息
private List<ScanResult> scanResultList; // 掃描出來的網絡鏈接列表
private List<WifiConfiguration> wifiConfigList;// 網絡配置列表
private WifiLock wifiLock;// Wifi鎖
public WifiManageClass(Context context) {
this.wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);// 獲取Wifi服務
// 獲得Wifi信息
this.wifiInfo = wifiManager.getConnectionInfo();// 獲得鏈接信息
}
public boolean getWifiStatus()
{
return wifiManager.isWifiEnabled();
}
// 打開/關閉 wifi
public boolean openWifi() {
if (!wifiManager.isWifiEnabled()) {
return wifiManager.setWifiEnabled(true);
} else {
return false;
}
}
public boolean closeWifi() {
if (!wifiManager.isWifiEnabled()) {
return true;
} else {
return wifiManager.setWifiEnabled(false);
}
}
// 鎖定/解鎖wifi
// 其實鎖定WiFI就是判斷wifi是否創建成功,在這裏使用的是held,握手的意思acquire 獲得!
public void lockWifi() {
wifiLock.acquire();
}
public void unLockWifi() {
if (!wifiLock.isHeld()) {
wifiLock.release(); // 釋放資源
}
}
// 我原本是寫在構造函數中了,可是考慮到不是每次都會使用Wifi鎖,因此乾脆本身創建一個方法!須要時調用,創建就OK
public void createWifiLock() {
wifiLock = wifiManager.createWifiLock("flyfly"); // 建立一個鎖的標誌
}
// 掃描網絡
public void startScan() {
wifiManager.startScan();
scanResultList = wifiManager.getScanResults(); // 掃描返回結果列表
wifiConfigList = wifiManager.getConfiguredNetworks(); // 掃描配置列表
}
public List<ScanResult> getWifiList() {
return scanResultList;
}
public List<WifiConfiguration> getWifiConfigList() {
return wifiConfigList;
}
// 獲取掃描列表
public StringBuilder lookUpscan() {
StringBuilder scanBuilder = new StringBuilder();
for (int i = 0; i < scanResultList.size(); i++) {
scanBuilder.append("編號:" + (i + 1));
scanBuilder.append(scanResultList.get(i).toString()); //全部信息
scanBuilder.append("\n");
}
return scanBuilder;
}
//獲取指定信號的強度
public int getLevel(int NetId)
{
return scanResultList.get(NetId).level;
}
// 獲取本機Mac地址
public String getMac() {
return (wifiInfo == null) ? "" : wifiInfo.getMacAddress();
}
public String getBSSID() {
return (wifiInfo == null) ? null : wifiInfo.getBSSID();
}
public String getSSID() {
return (wifiInfo == null) ? null : wifiInfo.getSSID();
}
// 返回當前鏈接的網絡的ID
public int getCurrentNetId() {
return (wifiInfo == null) ? null : wifiInfo.getNetworkId();
}
// 返回全部信息
public String getwifiInfo() {
return (wifiInfo == null) ? null : wifiInfo.toString();
}
// 獲取IP地址
public int getIP() {
return (wifiInfo == null) ? null : wifiInfo.getIpAddress();
}
// 添加一個鏈接
public boolean addNetWordLink(WifiConfiguration config) {
int NetId = wifiManager.addNetwork(config);
return wifiManager.enableNetwork(NetId, true);
}
// 禁用一個連接
public boolean disableNetWordLick(int NetId) {
wifiManager.disableNetwork(NetId);
return wifiManager.disconnect();
}
// 移除一個連接
public boolean removeNetworkLink(int NetId) {
return wifiManager.removeNetwork(NetId);
}
//不顯示SSID
public void hiddenSSID(int NetId)
{
wifiConfigList.get(NetId).hiddenSSID=true;
}
//顯示SSID
public void displaySSID(int NetId)
{
wifiConfigList.get(NetId).hiddenSSID=false;
}
}
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="adnroid.permission.ACCESS_CHECKIN_PROPERTTES"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="adnroid.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"></uses-permission>
android獲取第三方登錄
下面的是具體流程:
一、大家須要支持用戶註冊
二、大家須要在應用登陸的時候提供第三方平臺的圖標
三、用戶點擊第三方平臺圖標之後,大家嘗試判斷用戶是否已經受權
四、若是用戶受權,獲取他的惟一識別符,比方說WeiboDb裏面的weiboId這個字段
五、若是用戶沒有受權,引導用戶受權,受權成功後也能夠獲取weibo Id
六、而後用這個惟一識別符登陸大家的系統,若是用戶已經註冊,則應該讓用戶登陸到大家的系統,流程結束
七、若是大家的系統發現用戶沒有註冊,引導用戶進入大家應用的註冊頁面,並經過share sdk的showuser方法獲取用戶資料,自動幫助用戶完成註冊資料的填寫,而後等待用戶確認
八、若是用戶確認了註冊信息,大家的應用就根據他的信息完成這注冊操做,若是操做成功,則應該讓用戶登陸到大家的系統,流程結束
http://www.apkbus.com/android-125666-1-1.html
http://blog.csdn.net/qq435757399/article/details/8193790
Android 二維碼 生成和識別(附Demo源碼)
http://www.cnblogs.com/weixing/archive/2013/08/28/3287120.html