首页 文章 精选 留言 我的

精选列表

搜索[项目归档],共10000篇文章
优秀的个人博客,低调大师

Android 小项目之--解析如何获取SDCard 内存

继上篇音乐播放器,我们讲到使用 SDCard 播放音乐的例子,上篇也将如何在 Android 模拟器中创建 SDCard 的步骤列了出来。本篇将扩展上篇例子,去获取SDCard 的所存内存,显示出来告诉用户。本篇讲述的内容如下: 1、讲述 Environment 类。 2、讲述 StatFs 类。 3、完整例子读取 SDCard 内存 1、讲述 Environment 类 Environment是一个提供访问环境变量的类 。 Environment包含常量: MEDIA_BAD_REMOVAL 解释:返回getExternalStorageState(),表明SDCard 被卸载前己被移除 MEDIA_CHECKING 解释:返回getExternalStorageState(),表明对象正在磁盘检查。 MEDIA_MOUNTED 解释:返回getExternalStorageState(),表明对象是否存在并具有读/写权限 MEDIA_MOUNTED_READ_ONLY 解释:返回getExternalStorageState(),表明对象权限为只读 MEDIA_NOFS 解释:返回getExternalStorageState(),表明对象为空白或正在使用不受支持的文件系统。 MEDIA_REMOVED 解释:返回getExternalStorageState(),如果不存在 SDCard 返回 MEDIA_SHARED 解释:返回getExternalStorageState(),如果 SDCard 未安装 ,并通过 USB 大容量存储共享 返回 MEDIA_UNMOUNTABLE 解释:返回getExternalStorageState(),返回SDCard 不可被安装 如果 SDCard是存在但不可以被安装 MEDIA_UNMOUNTED 解释:返回getExternalStorageState(),返回 SDCard 已卸掉如果 SDCard 是存在但是没有被安装 Environment常用方法: 方法:getDataDirectory() 解释:返回 File ,获取 Android 数据目录。 方法:getDownloadCacheDirectory() 解释:返回 File ,获取 Android 下载/缓存内容目录。 方法:getExternalStorageDirectory() 解释:返回 File ,获取外部存储目录即 SDCard 方法:getExternalStoragePublicDirectory(Stringtype) 解释:返回 File ,取一个高端的公用的外部存储器目录来摆放某些类型的文件 方法:getExternalStorageState() 解释:返回 File ,获取外部存储设备的当前状态 方法:getRootDirectory() 解释:返回 File,获取 Android 的根目录 2、讲述 StatFs 类 StatFs一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况 StatFs常用方法: getAvailableBlocks() 解释:返回 Int ,获取当前可用的存储空间 getBlockCount() 解释:返回 Int ,获取该区域可用的文件系统数 getBlockSize() 解释:返回 Int ,大小,以字节为单位,一个文件系统 getFreeBlocks() 解释:返回 Int ,该块区域剩余的空间 restat(Stringpath) 解释:执行一个由该对象所引用的文件系统 3、完整例子读取 SDCard 内存 存储卡在 Android 手机上是可以随时插拔的,每次的动作都对引起操作系统进行 ACTION_BROADCAST,本例子将使用上面学到的方法,计算出 SDCard 的剩余容量和总容量。代码如下: package com.terry; import java.io.File; import java.text.DecimalFormat; import android.R.integer; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.StatFs; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class getStorageActivity extends Activity{ private ButtonmyButton; /** Calledwhentheactivityisfirstcreated. */ @Override public void onCreate(BundlesavedInstanceState){ super .onCreate(savedInstanceState); setContentView(R.layout.main); findView(); viewHolder.myButton.setOnClickListener( new OnClickListener(){ @Override public void onClick(Viewarg0){ // TODOAuto-generatedmethodstub getSize(); } }); } void findView(){ viewHolder.myButton = (Button)findViewById(R.id.Button01); viewHolder.myBar = (ProgressBar)findViewById(R.id.myProgressBar); viewHolder.myTextView = (TextView)findViewById(R.id.myTextView); } void getSize(){ viewHolder.myTextView.setText( "" ); viewHolder.myBar.setProgress( 0 ); // 判断是否有插入存储卡 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ Filepath = Environment.getExternalStorageDirectory(); // 取得sdcard文件路径 StatFsstatfs = new StatFs(path.getPath()); // 获取block的SIZE long blocSize = statfs.getBlockSize(); // 获取BLOCK数量 long totalBlocks = statfs.getBlockCount(); // 己使用的Block的数量 long availaBlock = statfs.getAvailableBlocks(); String[]total = filesize(totalBlocks * blocSize); String[]availale = filesize(availaBlock * blocSize); // 设置进度条的最大值 int maxValue = Integer.parseInt(availale[ 0 ]) * viewHolder.myBar.getMax() / Integer.parseInt(total[ 0 ]); viewHolder.myBar.setProgress(maxValue); StringText = " 总共: " + total[ 0 ] + total[ 1 ] + " \n " + " 可用: " + availale[ 0 ] + availale[ 1 ]; viewHolder.myTextView.setText(Text); } else if (Environment.getExternalStorageState().equals(Environment.MEDIA_REMOVED)){ Toast.makeText(getStorageActivity. this , " 没有sdCard " , 1000 ).show(); } } // 返回数组,下标1代表大小,下标2代表单位KB/MB String[]filesize( long size){ Stringstr = "" ; if (size >= 1024 ){ str = " KB " ; size /= 1024 ; if (size >= 1024 ){ str = " MB " ; size /= 1024 ; } } DecimalFormatformatter = new DecimalFormat(); formatter.setGroupingSize( 3 ); Stringresult[] = new String[ 2 ]; result[ 0 ] = formatter.format(size); result[ 1 ] = str; return result; } } TIP:要判断手机是否安装了存储卡,可通过 Environment.getExternalStorageState()方法来判断存储卡的状态。 如果你不知道如何创建 SDCard 你可回头看我上篇文章: 点击这里 实例运行效果如图 上篇放了两首歌和一个30多M的音频文件,之前创建时给的500MB空间,现在剩下的刚好。 源码下载: /Files/TerryBlog/getSdCardStorage.rar 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/340079,如需转载请自行联系原作者

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

阿里巴巴,排行前10的开源项目!

​ image 1、FastDFS FastDFS是一个开源的分布式文件系统,她对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。 2、Dubbo Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和 Spring 框架无缝集成。 3、Druid Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。 4、Fastjson fastjson是一个性能很好的Java语言实现的JSON解析器和生成器,来自阿里巴巴的工程师开发。 5、RocketMQ RocketMQ是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。 6、OceanBase OceanBase是一个支持海量数据的高性能分布式数据库系统,实现了数千亿条记录、数百TB数据上的跨行跨表事务,由淘宝核心系统研发部、运维、DBA、广告、应用研发等部门共同完成。 7、Weex Weex是一款跨平台移动开发工具,能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持iOS、安卓、YunOS及Web等多端部署。 8、Tair Tair是由淘宝网自主开发的Key/Value结构数据存储系统,在淘宝网有着大规模的应用。您在登录淘宝、查看商品详情页面或者在淘江湖和好友“捣浆糊”的时候,都在直接或间接地和Tair交互。 9、Tsar Tsar是淘宝的采集工具,主要用来收集服务器的系统信息(如cpu,io,mem,tcp等)以及应用数据(如squid haproxy nginx等),tsar支持实时查看和历史查看,方便了解应用和服务器的信息。 10、AliSQL AliSQL是基于MySQL官方版本的一个分支,由阿里云数据库团队维护,目前也应用于阿里巴巴集团业务以及阿里云数据库服务。该版本在社区版的基础上做了大量的性能与功能的优化改进。尤其适合电商、云计算以及金融等行业环境。 推荐阅读 2017派卧底去阿里、京东、美团、滴滴带回来的面试题及答案 Spring面试题(70道,史上最全) 云栖大会100位顶级大咖演讲PPT+视频全分享! 17张图揭密支付宝系统架构 【推荐】阿里双11背后的技术:不一样的技术创新,阿里巴巴技术演进与超越

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

创建Maven项目下的Dubbo+Zookeeper框架

互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架,在这种情况下诞生的。现在核心业务抽取出来,作为独立的服务,使前端应用能更快速和稳定的响应。 第一:Dubbo背景 大规模服务化,应用使用RMI或Hessian等工具,通过配置服务URL地址调用,通过F5等硬件进行负载均衡。 当然了,在系统越来越复杂的时候我们就面临三个问题: (1)当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。 此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。 (2)当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。 这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。 (3)接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器? 为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。 其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。 Dubbo就是基于Hessian实现了自己Hessian协议,可以直接通过配置的Dubbo内置的其他协议,在服务消费方进行远程调用,也就是说,服务调用方需要使用Java语言来基于Dubbo调用提供方服务,限制了服务调用方。 我们需要一个这样的界面: 第二:Dubbo简介 Dubbo的原理图: 节点角色说明: Provider:暴露服务的服务提供方。 Consumer:调用远程服务的服务消费方。 Registry:服务注册与发现的注册中心。 Monitor:统计服务的调用次调和调用时间的监控中心。 Container:服务运行容器。 调用关系说明: 0.服务容器负责启动,加载,运行服务提供者。 1.服务提供者在启动时,向注册中心注册自己提供的服务。 2.服务消费者在启动时,向注册中心订阅自己所需的服务。 3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 Dubbo提供了很多协议,Dubbo协议、RMI协议、Hessian协议,我们查看Dubbo源代码,有各种协议的实现,如图所示: 我们之前没用Dubbo之前时,大部分都使用Hessian来使用我们服务的暴露和调用,利用HessianProxyFactory调用远程接口。 上面是参见Github官网,接下来我们来介绍Dubbo、Zookeeper整合使用。 第三:Duboo与Zookeeper整合: 1、搭建Dubbo环境 1)、在Linux系统上安装JDK(使用1.7版本的jdk-7u25-linux-x64.tar.gz) 安装按照百度经验: Linux JDK安装及配置(tar.gz版) 2)、安装Zookeeper 按照博客: centos下zookeeper安装配置 3)、安装Tomcat 按照博客: CentOS-6.3安装配置Tomcat-7 4)、配置Dubbo-admin管理页面 按照博客: Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错) 这里我们需要注意一个地方: 下载dubbo-admin-2.4.1.war包,在Linux的tomcat部署,先将tomcat的webapps/Root文件夹下载的所有的文件删除,把dubbo-admin-2.4.1放在tomcat的webapps/Root下,然后进行解压: #jar-xvfdubbo-admin-2.4.1.war 第一开始的时候,我直接将dubbo-admin-2.4.1.war包解压到Root下面,结果,不能访问了。因此大家在这里注意一下。 注:大家要记得关闭防火墙: systemctlstopfirewalld.service#停止 本文转自yzy121403725 51CTO博客,原文链接:http://blog.51cto.com/lookingdream/1948553,如需转载请自行联系原作者

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

Android 小项目之--数据存储【Network】(附源码)

将数据保存发送到电子邮件中备份,首要前提应该先在模拟器中设置好电子邮件帐户,设置如下: 第一步,启动模拟器,打开“菜单”,选择“电子邮件”项,填写相应帐号和密码。 第二步,点击NEXT,程序自动配置电子邮件相关信息。 第三步,配置完成后,输入相应的名称信息,即可设置完成,接下来程序会默认帮你导入你输入邮箱帐号的相关信息 业务逻辑如下:示例中有一个文本框用来模拟用户的信息,当程序退出的时候保存文本档的信息,并转到发送邮件的页面,让用户把信息保存到邮箱 里面。具体代码参考如下: 发送信息保存到邮箱 package com.terry; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.KeyEvent; import android.widget.EditText; public class networkActivity extends Activity{ private EditTextmyEditText; /** Calledwhentheactivityisfirstcreated. */ @Override public void onCreate(BundlesavedInstanceState){ super .onCreate(savedInstanceState); setContentView(R.layout.main); myEditText = (EditText)findViewById(R.id.myEditText4); } @Override public boolean onKeyDown( int keyCode,KeyEventevent){ // TODOAuto-generatedmethodstub if (keyCode == KeyEvent.KEYCODE_BACK) { // 发送邮件地址 Uriuri = Uri.parse( " mailto:285735942@qq.com " ); // 创建intent Intentit = new Intent(Intent.ACTION_SENDTO,uri); it.putExtra(android.content.Intent.EXTRA_SUBJECT, " 网络存储 " ); it.putExtra(android.content.Intent.EXTRA_TEXT,myEditText.getText()); startActivity(it); this .finish(); return true ; } return super .onKeyDown(keyCode,event); } } 扩展 既然发送数据保存到网络上,当然也可以获得网络上的数据,下面我们通过一个小例子来实现从网路上加载一个txt文件的小说程序 。如图: 逻辑代码如下:首先创建一个我们要访问的URL地址,然后取链接的文件,循环把数据读取出来。具体代码参考如下: 读取XML代码参考 package com.terry; import java.io.BufferedInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import org.apache.http.util.ByteArrayBuffer; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class readxmlActivity extends Activity{ @Override protected void onCreate(BundlesavedInstanceState){ // TODOAuto-generatedmethodstub super .onCreate(savedInstanceState); setContentView(R.layout.readxml); TextViewtv = (TextView)findViewById(R.id.TextView01); Stringmsg = "" ; try { URLurl = new URL( " http://www.az1314.com/txt/00.txt " ); // 要访问的数据文件 URLConnectioncon = url.openConnection(); InputStreamis = con.getInputStream(); BufferedInputStreambis = new BufferedInputStream(is); ByteArrayBufferbaf = new ByteArrayBuffer( 100 ); int current = 0 ; while ((current = bis.read()) != - 1 ){ baf.append(( byte )current); } msg = new String(baf.toByteArray()); } catch (Exceptione){ // TODO:handleexception msg = e.getMessage(); } tv.setText(msg); } } 方法讲解: URL共有六种构造方法,分别如下: URL(Stringspec) 通过传进来的字符串分析,创建一个新的URL实例。 URL(URLcontext,Stringspec) 通过传进来的字符串分析,创建一个新的URL实例。需要一个URL的参数 URL(URLcontext,Stringspec,URLStreamHandlerhandler) 通过传进来的字符串分析,创建一个新的URL实例 URL(Stringprotocol,Stringhost,Stringfile) 使用给定的参数创建一个URL实例,需要指定协议,主机文件名 URL(Stringprotocol,Stringhost, int port,Stringfile) 使用给定的参数创建一个URL实例,需要指定协议,主机,端口和文件名 URL(Stringprotocol,Stringhost, int port,Stringfile,URLStreamHandlerhandler) 使用给定的参数创建一个URL实例,需要指定协议,主机,端口、文件名和处理程序 URLConnection介绍: 用以来实现提供一个具有特定协议类的连接源。 getInputStream 主要用来读取一个URLConnection的资源数据,返回一个InputStream,本文将使用这个方法获取数据 在此不多介绍URLConnection此类,感兴趣的朋友可以查看一下SDK。代码如上,运行效果图: 因为在模拟器运行。 出现乱码了,如果你有真机不妨在真机上试试。 Tip: 访问外部网络需要在配置文件中给予权限,如果你没有权限将会出现如下界面: 权限代码如下: android:versionCode="1" android:versionName="1.0"> < application android:icon ="@drawable/icon" android:label ="@string/app_name" > < activity android:name =".networkActivity" android:label ="@string/app_name" > </ activity > < activity android:name =".readxmlActivity" >< intent-filter > < action android:name ="android.intent.action.MAIN" /> < category android:name ="android.intent.category.LAUNCHER" /> </ intent-filter ></ activity > </ application > < uses-permission android:name ="android.permission.INTERNET" /> 至此四种数据存储完结。 源码下载: /Files/TerryBlog/NetworkdDemo.rar 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/336756,如需转载请自行联系原作者

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

使用NDK移植开源项目,JNI的使用技巧

Jni 的介绍 JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。以下介绍Android 中如何使用jni移植开源库的技巧. JNI日志输出到Logcat中 #include <android/log.h> #define LOG_TAG "===xcloud===" #define LOGI(...) android_log_print(ANDROID_LOG_INFO,LOG_TAG,VA_ARGS__) #define LOGW(...) android_log_print(ANDROID_LOG_WARN,LOG_TAG,VA_ARGS__) #define LOGE(...) android_log_print(ANDROID_LOG_ERROR,LOG_TAG,VA_ARGS__) Android.mk文件添加编译模块: LOCAL_LDLIBS=-lm -llog 使用方法: LOGE("%s",test); JNI调用Java方法 以调用String 的getBytes方法为例: 第一步: jclass clsstring = (*env)->FindClass(env,"java/lang/String"); //找到Java String 类 第二步: jstring strencode = (*env)->NewStringUTF(env,"utf-8"); //得到一个jstring 对象 第三步: jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); //得到getBytes方法 第四步: jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr, mid, strencode); //“jstr 为传入的字符串”调用getBytes方法 第五步: jsize alen = (*env)->GetArrayLength(env,barr); //得到数组长度 jstring 转换 char* char* test=(char*)(*env)->GetStringUTFChars(env,jstringVariable,NULL); 返回一个java对象数组 第一步: jclass objectClass=(*env)->FindClass(env,"com/xuzhitech/xcloud/resource"); //找到对应的java 类(对象) 第二步: jobjectArray array=(*env)->NewObjectArray(env,currentListCount,objectClass,NULL); //通过取到的java类(对象)创建一个指定固定大小的数组 第三步: jfieldID _uri=(*env)->GetFieldID(env,objectClass,"uri","Ljava/lang/String;");//找到对象中的列 注意:在JNI中并未提供jstring 类型的对象,所以必须通过L指定包名找到该类,在有提供的类型中,可以直接使用该类型的大写首字母(jlong 需使用J) 如jint 类型可以如此编写: jfieldID _vcr=(*env)->GetFieldID(env,objectClass,"is_vcr","I");对应的JNI提供类型可以参考如下 http://download.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html 第四步: jmethodID jid = (*env)->GetMethodID(env,objectClass,"<init>","()V");//"<init>"代表可以访问默认构造函数 jobject jobj=(*env)->NewObject(env,objectClass,jid); //通过第一步找到的jclass创建对应的对象 第五步: (*env)->SetObjectField(env,jobj,_modtime,jmodtime); //为对象中的每一列赋值。注意:如果JNI有提供的数据类型,可按提供的类型为对象中的列赋值, 如:(*env)->SetIntField(env,jobj,_vcr,current->is_vcr); 第六步: (*env)->SetObjectArrayElement(env,array,i,jobj);将对象设置进第二步声明的数组中 DeleteLocalRef(env,jobj);//删除引用对象 在JNI中循环读取对象数组 for(i= 0;i<currentListCount;i++){ jobjectobj=(*env)->GetObjectArrayElement(env,array,i); jstringjstr=(*env)->GetObjectField(env,obj,_uri); LOGE( " =====uri===%s==== ",jstringtoChar(env,jstr)); } 上面使用到的jstringtoChar方法代码: /* * *jstringtochar */ char*jstringtoChar(JNIEnv*env,jstringjstr){ char*rtn=NULL; jclassclsstring=(*env)->FindClass(env, " java/lang/String "); jstringstrencode=(*env)->NewStringUTF(env, " utf-8 "); jmethodIDmid=(*env)->GetMethodID(env,clsstring, " getBytes ", " (Ljava/lang/String;)[B "); jbyteArraybarr=(jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); jsizealen=(*env)->GetArrayLength(env,barr); jbyte*ba=(*env)->GetByteArrayElements(env,barr,JNI_FALSE); if(alen> 0) { rtn=( char*)malloc(alen+ 1); memcpy(rtn,ba,alen); rtn[alen]= 0; } (*env)->ReleaseByteArrayElements(env,barr,ba, 0); returnrtn; } cpp JNI与 c JNI的主要注意事项: 用C编写jni文件,访问JNI内置提供方法格式: (*env)->SetObjectArrayElement(env,array,i,jobj); 用CPP编写JNI文件,访问JNI内置提供方法格式: env->SetObjectArrayElement(array,i,jobj); 另外,使用CPP编写的JNI代码,在调用C语言编写的库的时候,要添加以下代码,才可以正常使用(不然在链接的时候找不到相关接口:undefined reference.....): ifdef __cplusplus extern "C" { #endif ... //引入的头文件 #ifdef __cplusplus } #endif 其他用法几乎一致。 JNI 使用Native注册 按照上面的方法写函数体,必须遵循JNI官方的一大堆标准进行方法的定义,有时候方法一多,不大好管理,也不利用查看,并且每次都要写一大堆恶心的标准方法名也不是一件好事。对此JNI有一套可以通过Native 注册的机制可以使用,以方便函数体的编写。 以下是Android 调用JNI注册Natives 的步骤: 第一步 声明Java中要调用jni 的类路径: static const char *className="com/xuzhitech/xcloud/cadaver"; 第二步 创建方法格式结构体: struct JNINativeMethod { const char* name;//method name const char* signature; //java method return value void* fnPtr;//c/c++ method } ; 第三步 使用结构体注册需要供Android 调用的方法体: staticJNINativeMethodmethods[]={ { " StringTestOne ", " ()Ljava/lang/String; ",( void*)StringTestOne}, { " executels ", " ()[Lcom/xuzhitech/xcloud/resource; ",( void*)executels}, { " getProgress ", " ()Lcom/xuzhitech/xcloud/fileProgress; ",( void*)getProgress}, { " getdownloadState ", " ()I ",( void*)getdownloadState}, { " changeExecutable ", " (Ljava/lang/String;Ljava/lang/String;)I ",( void*)changeExecutable}, { " Login ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)Login}, { " getCurrentListCount ", " ()I ",( void*)getCurrentListCount}, { " mkcol ", " (Ljava/lang/String;)I ",( void*)mkcol}, { " deleteFile ", " (Ljava/lang/String;)I ",( void*)deleteFile}, { " deleteCol ", " (Ljava/lang/String;)I ",( void*)deleteCol}, { " getFullUri ", " ()Ljava/lang/String; ",( void*)getFullUri}, { " cdCommand ", " (Ljava/lang/String;)I ",( void*)cdCommand}, { " logout ", " ()V ",( void*)logout}, { " doCopy ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)doCopy}, { " doMove ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)doMove}, { " getFile ", " (Ljava/lang/String;Ljava/lang/String;)V ",( void*)getFile}, { " putFile ", " (Ljava/lang/String;Ljava/lang/String;)V ",( void*)putFile}, { " lock ", " (Ljava/lang/String;)I ",( void*) lock}, { " unlock ", " (Ljava/lang/String;Ljava/lang/String;)I ",( void*)unlock}, { " getToken ", " (Ljava/lang/String;)Ljava/lang/String; ",( void*)getToken}, { " isSetToken ", " (Ljava/lang/String;)I ",( void*)isSetToken}, }; 第一个参数为:Java实现要调用的方法名称 第二个参数为:该方法需要的返回值与方法参数,如->(方法参数)返回值,详细使用参考如下: 具体的每一个字符的对应关系如下 字符 Java类型 C类型 V void void Zjbooleanboolean Ijint int Jjlong long Djdouble double Fjfloat float Bjbyte byte Cjchar char Sjshort short 数组则以"["开始,用两个字符表示 [IjintArray int[] [FjfloatArray float[] [BjbyteArray byte[] [CjcharArray char[] [SjshortArray short[] [DjdoubleArray double[] [JjlongArray long[] [ZjbooleanArrayboolean[] 也可返回任意java对象,如上代码的()[Lcom/xuzhitech/xcloud/resource;代表一个不带参数的方法,并且返回java类中的Lcom/xuzhitech/xcloud/resource;数组。'['代表数组的意思,'L'代表类的意思 第三个参数为,第一个参数需要映射的本地c/c++对应的函数指针方法。 第四步 在加载jni的时候指定JNI版本并且通过传入进来的class路径注册Natives 方法 jintJNI_OnLoad(JavaVM*vm, void *reserved){ jintresult=JNI_ERR; JNIEnv*env=NULL; jclassclazz;intmethodsLenght;if((*vm)->GetEnv(vm,(void**)&env,JNI_VERSION_1_4)!=JNI_OK){ LOGE("ERROR:GetEnvfailed\n");returnJNI_ERR; }//assert(env!=NULL);clazz=(*env)->FindClass(env,className);if(clazz==NULL){ LOGE("Nativeregistrationunabletofindclass'%s'",className);returnJNI_ERR; } methodsLenght=sizeof(methods)/sizeof(methods[0]);if((*env)->RegisterNatives(env,clazz,methods,methodsLenght)<0){ LOGE("RegisterNativesfailedfor'%s'",className);returnJNI_ERR; }//result=JNI_VERSION_1_4;returnresult; } 注意,使用Natives注册运行程序时,它会先检测jni与java类使用jni 类的native 方法是否相对应与一致,即使你没有使用到该 方法也会进行检测。 第五步 通过上面的修改,c/c++编写的jni 文件就可以不带一大串标准名称了,您可以像正常编写c一样编写你的jni函数,如下: /* *movefile */ jintdoMove(JNIEnv*env,jobjectthiz,jstringjsrc,jstringjdest,jstringjrename){ char*src=( char*)(*env)->GetStringUTFChars(env,jsrc,NULL); char*dest=( char*)(*env)->GetStringUTFChars(env,jdest,NULL); char*rename=( char*)(*env)->GetStringUTFChars(env,jrename,NULL); intreturnValue=multi_move(src,dest,rename); // free(src); (*env)->ReleaseStringUTFChars(env,jsrc,src); // free(dest); (*env)->ReleaseStringUTFChars(env,jdest,dest); // free(rename); (*env)->ReleaseStringUTFChars(env,jrename,rename); returnreturnValue; } 注: JNI的一些基本方法的使用都可以参考这个网站:http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/792442,如需转载请自行联系原作者

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

对一个“失败”项目的审视—架构

衡量一个产品的成败,往往所站的角度不同理解也就不同。站在一个开发人员的角度来看,判断一个产品是否成功,往往首先判断这款产品是否满足用户的需求。对于有性能扩展要求的产品,则还要考虑其是否具有较高的性能、是否便于后期扩展;对于具有代码洁癖的开发者来说,则还要看代码编写是否规范等等。 今天我们先来了解一下这款产品的架构是如何设计的,再说说它的各服务器的功能。 首先我简单说明一下架构中需要重点考虑的几点: 1:网吧断网时的处理:架构设计中要考虑到网吧和中心服务器断网的情况,所以简单的按照MMO游戏的设计方式是不可行的(这种情况虽不常见,但是经常会由于网络不稳定而出现,有时也会因为一些其它原因而导致,例如某地区曾出现一整年断网情况),所以架构设计时需要处理:当网吧服务器和中心服务器断开后,网吧要能进行正常的业务处理;同时,当网吧服务器和中心服务器重新建立连接以后,需要将网吧在断线时间段内所处理的所有数据重新的发送到中心服务器上,并进行继续处理。 2:网吧业务连续性:对于网吧业务来说会存在一定的业务连续性,例如网吧的业务一定是先上机,后下机。这种业务如果处理顺序错乱,后果不堪设想。 3:网吧数据不准确:由于可能出现网吧网管勾结外部人员修改网吧营业数据的情况,因此网吧本地的数据不存在可信性(这里的数据指的是诸如营业流水等数据),需要中心服务器记录网吧所有的营业情况,并以重新计算得到的数据为准。 4:网吧数据产生的时段性:去过网吧的人都知道,网吧在一天之中业务数据产生的时间并非都是均匀的,例如在晚上10点以后到第二天7点左右(各网吧情况不同而定)一般是很少产生业务数据的,因为这段时间属于通宵包机时间;而在早晨8-9点属于网吧清场开业时间,这段时间会有数据大量产生。同时在周末的时候网吧也会出现业务数据产生的高峰期。基于以上的情况,架构的设计要能处理网吧业务数据瞬间变高的情况。 以上4点是系统设计时所要重点考虑的,尤其是第一点(是不是觉得考虑得很周到?但我要剧透的是,这种面面俱到的考虑其实是华丽丽的自虐。这个问题我以后会详说)。 我设计的架构图是这样的: 在这个架构中每个核心服务器的功能概要说明: 1:网关服务器: (1):用来接收大量的并发网吧服务端连接请求。 (2):接收网吧服务端的业务请求后,根据请求类型进行分析,并将请求发送给相应的后端业务处理服务器。 (3):接收后端业务处理服务器返回的业务处理数据,并将此数据转发给相应的网吧服务端。 2:帐号服务器: (1):对网吧的帐号信息进行合法性验证。 3:上报服务器: (1):接收网吧业务中需要上报的业务(例如:用户上机、下机、加钱、积分转换等等)进行业务逻辑处理。 (2):由于网吧业务存在前后逻辑关系,因此在处理的时候需要对网吧上传的业务进行顺序性处理。 4:同步服务器: (1):检测网吧服务端相关数据是否和中心数据库中的一致(费率数据、会员数据、营业流水等等),对于不一致的数据,采用同步方式强行让网吧数据和中心数据库数据一致。 外围服务器功能概要说明: 1:负载均衡服务器: (1):针对网吧帐号、所在区域等等信息对网吧应该连接的反向代理服务器的IP和端口进行指定。 (2):为了防止恶意连接反向代理服务器,负载均衡服务器为每一个网吧生成具有一定时效性的session。 (3):接收反向代理服务器的消息,对网吧帐号和session进行认证。 2:日志服务器: (1):记录所有服务器的日志信息。 (2):对所有日志进行相关分析,提取出Error级别的日志,并将此类日志保存在数据库中。 3:监控服务器: (1):监控所有服务器的运行情况,对于出现异常而宕掉的服务器程序进行自动运行,并向相关负责人发送短信报警。 (2):定时从Error日志数据库中提取相关日志,并将信息进行汇总后以短信(邮件)的方式发送给相关责任人。 本文转自狗窝博客51CTO博客,原文链接http://blog.51cto.com/fxh7622/1535702如需转载请自行联系原作者 fxh7622

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

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

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

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

用户登录
用户注册