首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

开发者笔记】MQTT python测试笔记

MQTT是基于订阅/发布的物联网协议。 python测试需要一个发送进程和接收进程,即一个发送客户端和一个接收客户端,如果这两个客户端工作在同一个topic下,那么就能进行消息互通了。 服务器用“iot.eclipse.org”就好了,避免了自己搭建服务器,然后流程还可以跑通。 发送客户端代码: import paho.mqtt.client as mqtt import paho.mqtt.publish as publish idx = 0#往paho/temperature 一直发送内容 while True: print("send success") publish.single("paho/temperature", payload="this is message:%s"%idx, hostname="iot.eclipse.org", client_id="lora1", # qos = 0, # tls=tls, port=1883, protocol=mqtt.MQTTv311) idx += 1 接收客户端代码: import paho.mqtt.client as mqtt # The callback for when the client receives a CONNACK response from the server. def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) # The callback for when a PUBLISH message is received from the server. def on_message(client, userdata, msg): #在这里处理业务逻辑 print(msg.topic+" "+str(msg.payload)) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("iot.eclipse.org", 1883, 60)#订阅频道 client.subscribe("paho/temperature") # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting. # Other loop*() functions are available that give a threaded interface and a # manual interface. client.loop_forever() 然后运行两个客户端,就可以在接收端收到消息了。 MQTT服务器不负责存储数据,需要编写额外的接收客户端来接收数据、分析、入库等。 MQTT服务器用的是iot.eclipse.org,如果碰巧两个人在用同一个频道,那可能收到别人的消息哦~ 如果要搭建自己的MQTT服务器,那么回头再说。 玩一玩就好了,不要给服务器增加太多负担哟~ 参考资料: paho-qtt说明文档 黑夜给了我黑色的眼睛,我却用它寻找光明

优秀的个人博客,低调大师

Android开发实践:多级列表的封装与应用

Android中多级列表可以使用ExpandableListView和SimpleExpandableListAdapter配合来实现,但是,SimpleExpandableListAdapter用起来挺麻烦的,不易理解,而且扩展性也不好,因此,自定义BaseExpandableListAdapter类的子类以及封装相关的操作,用起来会更加直观和方便,我把我设计的封装贴出来供新手参考吧。 首先上效果图,如图所示: 1. 首先设计多级列表的标题类 就像文件和文件夹可以统一地用File类来抽象一样,多级列表的一级标题和二级标题其实也可以用同一个基类来抽象,因此,我设计了一个基类和两个子类,GroupList,GroupListChild 和 GroupListParent,其实现如下所示: (1) GroupList 多级列表标题的抽象基类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public abstract class GroupList{ private final StringmTitle; public GroupList(Stringtitle){ mTitle=title; } public StringgetTitle(){ return mTitle; } public abstract List<GroupList>getChild(); public abstract int getResource(); public abstract void buildView(Viewv); } (2) GroupListChild 多级列表二级标题子类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class GroupListChild extends GroupList{ public GroupListChild(Stringtitle){ super (title); } @Override public int getResource(){ return R.layout.grouplist_child; } @Override public List<GroupList>getChild(){ return null ; } @Override public void buildView(Viewv){ TextViewtextView=(TextView)v.findViewById(R.id.GroupListChild); textView.setText(getTitle()); } } (3) GroupListParent 多级列表一级标题子类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class GroupListParent extends GroupList{ private List<GroupList>mPopListChilds; public GroupListParent(Stringtitle,List<GroupList>childs){ super (title); mPopListChilds=childs; } @Override public int getResource(){ return R.layout.grouplist_parent; } @Override public List<GroupList>getChild(){ return mPopListChilds; } @Override public void buildView(Viewv){ TextViewtextView=(TextView)v.findViewById(R.id.GroupListParent); textView.setText(getTitle()); } } 2. 设计BaseExpandableListAdapter的子类 我设计的子类是一种通用的Adapter子类,类的实现中并不包含具体的Layout实现,所有的Layout都由GroupList的getResource和buildView来负责,因此,可以非常灵活地修改Layout的具体实现,而不用修改Adapter的代码。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public class GroupListAdapter extends BaseExpandableListAdapter{ private ContextmContext; private List<GroupList>mGroups; public GroupListAdapter(Contextcontext,List<GroupList>groups){ this .mContext=context; this .mGroups=groups; } @Override public ObjectgetChild( int groupPosition, int childPosition){ List<GroupList>chList=mGroups.get(groupPosition).getChild(); if (chList== null ){ return null ; } return chList.get(childPosition); } @Override public long getChildId( int groupPosition, int childPosition){ return childPosition; } @Override public ViewgetChildView( int groupPosition, int childPosition, boolean isLastChild,Viewview,ViewGroupparent){ GroupListchild=(GroupList)getChild(groupPosition,childPosition); if (child== null ){ return null ; } if (view== null ){ LayoutInflaterinflater=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view=(RelativeLayout)inflater.inflate(child.getResource(), null ); } child.buildView(view); return view; } @Override public int getChildrenCount( int groupPosition){ List<GroupList>chList=mGroups.get(groupPosition).getChild(); if (chList== null ){ return 0 ; } return chList.size(); } @Override public ObjectgetGroup( int groupPosition){ return mGroups.get(groupPosition); } @Override public int getGroupCount(){ return mGroups.size(); } @Override public long getGroupId( int groupPosition){ return groupPosition; } @Override public ViewgetGroupView( int groupPosition, boolean isLastChild,Viewview,ViewGroupparent){ GroupListgroup=(GroupList)getGroup(groupPosition); if (view== null ){ LayoutInflaterinflater=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view=(RelativeLayout)inflater.inflate(group.getResource(), null ); } group.buildView(view); return view; } @Override public boolean hasStableIds(){ return true ; } @Override public boolean isChildSelectable( int arg0, int arg1){ return true ; } } 3. 应用代码 为了简化,我就直接在MainActivity中使用上述封装的类来完成多级列表的功能演示,示例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public class MainActivity extends Activity implements OnGroupClickListener,OnChildClickListener{ private ExpandableListViewmlistView; private GroupListAdaptermAdapter; private static final String[]mParentMenu={ "Book" , "Video" , "Audio" }; private static final String[][]mChildMenu={ { "book1" , "book2" , "book3" , "book4" }, { "video1" , "video2" }, { "audio1" , "audio2" , "audio3" , "audio4" } }; @Override protected void onCreate(BundlesavedInstanceState){ super .onCreate(savedInstanceState); mlistView= new ExpandableListView( this ); mlistView.setOnGroupClickListener( this ); mlistView.setOnChildClickListener( this ); List<GroupList>groups= new ArrayList<GroupList>(); for ( int i= 0 ;i<mParentMenu.length;i++){ List<GroupList>childs= new ArrayList<GroupList>(); for ( int j= 0 ;j<mChildMenu[i].length;j++){ childs.add( new GroupListChild(mChildMenu[i][j])); } groups.add( new GroupListParent(mParentMenu[i],childs)); } mAdapter= new GroupListAdapter( this ,groups); mlistView.setAdapter(mAdapter); setContentView(mlistView); } @Override public boolean onChildClick(ExpandableListViewparent,Viewv, int groupPosition, int childPosition, long id){ return false ; } @Override public boolean onGroupClick(ExpandableListViewparent,Viewv, int groupPosition, long id){ return false ; } } 4. 相关的xml文件 (1) grouplist_child.xml 文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <? 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" android:orientation = "horizontal" > < TextView android:id = "@+id/GroupListChild" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:textColor = "#FFFF0000" android:layout_margin = "10dp" android:layout_centerInParent = "true" /> </ RelativeLayout > (2) grouplist_parent.xml 文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <? 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" android:orientation = "horizontal" > < TextView android:id = "@+id/GroupListParent" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:textColor = "@android:color/black" android:textStyle = "bold" android:layout_margin = "10dp" android:layout_centerInParent = "true" /> </ RelativeLayout > 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1289642,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发实践:WIFI连接功能的封装

与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果。该回调接口的定义如下: 1 2 3 public interface WifiConnectListener{ public void OnWifiConnectCompleted( boolean isConnected); } 从Android的WIFI Setting可以看出,一般添加一个新的WIFI连接,需要给出三个信息,一个是WIFI的SSID,一个是WIFI的密码,另一个是WIFI的加密类型,不同的加密方式,连接时程序中的配置是不同的,这里定义一个枚举,给出四种常见的加密类型: 1 2 3 public enum SecurityMode{ OPEN,WEP,WPA,WPA2 } Android的WIFI连接过程,总体上分为三步,第一步,添加网络配置,第二步,根据网络配置连接WIFI,第三步,监听系统的WIFI连接状态消息。下面就直接给出示例代码,关键的地方都在代码中注释了。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 package com.example.testwifi; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; public class WifiConnector{ private static final int WIFI_CONNECT_TIMEOUT= 20 ; //连接WIFI的超时时间 private ContextmContext; private WifiManagermWifiManager; private LockmLock; private ConditionmCondition; private WiFiConncetReceivermWifiConnectReceiver; private WifiConnectListenermWifiConnectListener; private boolean mIsConnnected= false ; private int mNetworkID=- 1 ; //网络加密模式 public enum SecurityMode{ OPEN,WEP,WPA,WPA2 } //通知连接结果的监听接口 public interface WifiConnectListener{ public void OnWifiConnectCompleted( boolean isConnected); } public WifiConnector(Contextcontext,WifiConnectListenerlistener){ mContext=context; mLock= new ReentrantLock(); mCondition=mLock.newCondition(); mWifiManager=(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); mWifiConnectReceiver= new WiFiConncetReceiver(); mWifiConnectListener=listener; } public void connect( final Stringssid, final Stringpassword, final SecurityModemode){ new Thread( new Runnable(){ @Override public void run(){ //如果WIFI没有打开,则打开WIFI if (!mWifiManager.isWifiEnabled()){ mWifiManager.setWifiEnabled( true ); } //注册连接结果监听对象 mContext.registerReceiver(mWifiConnectReceiver, new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)); //连接指定SSID if (!onConnect(ssid,password,mode)){ mWifiConnectListener.OnWifiConnectCompleted( false ); } else { mWifiConnectListener.OnWifiConnectCompleted( true ); } //删除注册的监听类对象 mContext.unregisterReceiver(mWifiConnectReceiver); } }).start(); } protected boolean onConnect(Stringssid,Stringpassword,SecurityModemode){ //添加新的网络配置 WifiConfigurationcfg= new WifiConfiguration(); cfg.SSID= "\"" +ssid+ "\"" ; if (password!= null &&! "" .equals(password)){ //这里比较关键,如果是WEP加密方式的网络,密码需要放到cfg.wepKeys[0]里面 if (mode==SecurityMode.WEP){ cfg.wepKeys[ 0 ]= "\"" +password+ "\"" ; cfg.wepTxKeyIndex= 0 ; } else { cfg.preSharedKey= "\"" +password+ "\"" ; } } cfg.status=WifiConfiguration.Status.ENABLED; //添加网络配置 mNetworkID=mWifiManager.addNetwork(cfg); mLock.lock(); mIsConnnected= false ; //连接该网络 if (!mWifiManager.enableNetwork(mNetworkID, true )){ mLock.unlock(); return false ; } try { //等待连接结果 mCondition.await(WIFI_CONNECT_TIMEOUT,TimeUnit.SECONDS); } catch (InterruptedExceptione){ e.printStackTrace(); } mLock.unlock(); return mIsConnnected; } //监听系统的WIFI连接消息 protected class WiFiConncetReceiver extends BroadcastReceiver{ @Override public void onReceive(Contextcontext,Intentintent){ if (!WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())){ return ; } mLock.lock(); WifiInfoinfo=mWifiManager.getConnectionInfo(); if (info.getNetworkId()==mNetworkID&&info.getSupplicantState()==SupplicantState.COMPLETED){ mIsConnnected= true ; mCondition.signalAll(); } mLock.unlock(); } } } 与WIFI扫描的封装代码类似,这里也用到了Lock和Condition,就是为了阻塞地等待WIFI连接的结果,保证正确的registerReceiver和unregisterReceiver网络连接状态监听对象,同时,设置了WIFI连接超时,防止由于WIFI模块的问题导致界面收不到回调而长时间“卡死”。 另外,AndroidManifest.xml文件中记得添加权限支持哦: 1 2 3 <uses-permissionandroid:name= "android.permission.CHANGE_WIFI_STATE" ></uses-permission> <uses-permissionandroid:name= "android.permission.ACCESS_WIFI_STATE" ></uses-permission> <uses-permissionandroid:name= "android.permission.ACCESS_NETWORK_STATE" ></uses-permission> 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1410080,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发实践:在任意目录执行NDK编译

本文暂时不讲述如何用NDK编译第三方开源代码库,而是先以简单的例子讲述如何在任意目录把自己写的C代码编译成Android可使用的静态库/动态库。 1. 准备环境 首先,你得安装了Android的NDK编译工具,假设你的NDK的根目录在 /opt/android/ndk . 当然,最好你能在环境变量里配置一下路径,否则使用ndk-build命令的时候,都得加上路径的前缀了。 修改 ~/.bashrc 1 2 export NDK_HOME= /opt/android/ndk export PATH=$NDK_HOME:$PATH 然后执行: 1 $ source ~/.bashrc 2. 编写 .c 文件 假设你在 ~/math 目录下编写了一个 math.c 文件,内容如下: 1 2 3 4 5 #include<stdio.h> int add( int a, int b){ return a+b; } OK,后面我们就准备在 ~/math 目录下,将这个.c文件编译为Android可使用的静态库/动态库了。 3. 编译成动态库 编写 Android.mk 文件,内容如下: 1 2 3 4 5 6 LOCAL_PATH:=$(callmy- dir ) include$(CLEAR_VARS) LOCAL_MODULE:=dmath LOCAL_SRC_FILES:=math.c include$(BUILD_SHARED_LIBRARY) 在 ~/math 目录下,执行 ndk-build 命令,参数如下: 1 $ndk-buildNDK_PROJECT_PATH=.APP_BUILD_SCRIPT=. /Android .mk 根据前一篇文章,我们可以知道,NDK_PROJECT_PATH 指定了需要编译的代码的工程目录,这里给出的是当前目录,APP_BUILD_SCRIPT给出的是Android makefile文件的路径,当然,如果你还有 Application.mk 文件的话,则可以添加 NDK_APP_APPLICATION_MK=./Application.mk 执行完ndk-build命令后,你会发现当前目录下,生成了 obj 和 libs 文件夹,这样,你的libdmath.so动态库就已经制作完成了,在 libs/armeabi 目录下。 4. 编译为静态库 编译为静态库,与编译为动态库唯一的区别就是 Android.mk 文件的写法不同,另外,如果要编译为静态库,则必须有其他的代码引用该静态库代码,ndk-build才会真正执行,否则无法成功生成静态库,这里,我们编写一个 Android.mk ,将 math.c 同时编译成静态库和动态库。 1 2 3 4 5 6 7 8 9 10 11 12 LOCAL_PATH:=$(callmy- dir ) include$(CLEAR_VARS) LOCAL_MODULE:=smath LOCAL_SRC_FILES:=math.c include$(BUILD_STATIC_LIBRARY) include$(CLEAR_VARS) LOCAL_MODULE:=dmath LOCAL_STATIC_LIBRARIES:=smath LOCAL_SRC_FILES:=math.c include$(BUILD_SHARED_LIBRARY) 同样,在 ~/math 目录下执行: 1 $ndk-buildNDK_PROJECT_PATH=.APP_BUILD_SCRIPT=. /Android .mk 你会在生成的 libs/armeabi 目录下看到动态库libdmath.so,在 obj/local/armeabi 目录下看到静态库 libsmath.a 关于在任意目录将c/c++代码编译为Android可使用的静态库/动态库就介绍到这里了,了解了这个编译过程,对你将来用ndk编译第三方库会很有帮助,另外,如果希望编译为C/C++应用程序在Android机器上运行的话,只需要在代码中加一个main函数,修改Android.mk中的最后一行为 include $(BUILD_EXECUTABLE) 即可。 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1428354,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册