2019独角兽企业重金招聘Python工程师标准>>>
Android设备应该通过何种方式,才能枚举局域网内的所有主机(这里的主机主要是指Android设备):
在双方没协议的情况下 试试循环Runtime.getRuntime().exec("ping "+ip+"-i 1 -c 2");
ping每个IP
Runtime.getRuntime().exec("arp -a >"+savefile);
再去处理savefile这个文件
另外就是发送udp广播了,请求方将自身ip和命令广播出去,设备收到命令将自身ip用tcp/udp发送给请求方。
每个设备要建立Socket监听广播才可以。
通过google提供的WifiManager类,我已经可以获取当前设备的IP,网关,和子网掩码。
这样的话,我已经可以计算出,当前局域网内所有可能的IP地址。
目前关于如何获知局域网内的其他设备,我有两个方案:
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线程接收到对方发过来的消息后就可以显示出来了
1、一种是自己写软件,类似飞鸽传书,自己进行UDP广播监听,就可以找到。
2、如果想用类似网上邻居那种,搜索下关于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
private ListView showiplistview;
public ArrayList
return ping;
}
public void setPing(ArrayList
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
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
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 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
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
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)“。
此外这个代码片段也设置了服务的类型,以定义应用程序所使用的传输层和传输协议。
具体语法规则中为”_
如果一个应用程序提供了打印服务就需要设置服务类型为"_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
private List
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
return scanResultList;
}
public List
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;
}
}
android获取第三方登陆
下面的是具体流程:
1、你们需要支持用户注册
2、你们需要在应用登录的时候提供第三方平台的图标
3、用户点击第三方平台图标以后,你们尝试判断用户是否已经授权
4、如果用户授权,获取他的唯一识别符,比方说WeiboDb里面的weiboId这个字段
5、如果用户没有授权,引导用户授权,授权成功后也可以获取weibo Id
6、然后用这个唯一识别符登录你们的系统,如果用户已经注册,则应该让用户登录到你们的系统,流程结束
7、如果你们的系统发现用户没有注册,引导用户进入你们应用的注册页面,并通过share sdk的showuser方法获取用户资料,自动帮助用户完成注册资料的填写,然后等待用户确认
8、如果用户确认了注册信息,你们的应用就根据他的信息完成这注册操作,如果操作成功,则应该让用户登录到你们的系统,流程结束
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