Bmob开发Android程序快速入门小demo菜鸟的学习

选择你要开发的应用,点击该应用下方对应的“应用密钥”

在跳转页面,获取ApplicationID,此ID将会在初始化SDK中使用到。

获取ApplicationID后,下载SDK,开发者可以根据自己的需求选择相应的iOSSDK或AndroidSDK,点击下载即可。

一、在你的项目根目录下创建"libs"目录,将下载的BmobSDK文件放入该目录下。

二、在你的应用程序中添加相应的权限:

packagecom.bmob.example;importcn.bmob.Bmob;importandroid.app.Activity;importandroid.os.Bundle;publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){//TODOAuto-generatedmethodstubsuper.onCreate(savedInstanceState);//初始化BmobSDK//使用时请将第二个参数ApplicationID替换成你在Bmob服务器端创建的ApplicationIDBmob.initialize(this,"YourApplicationID");}}简介Bmob平台为您的移动应用提供了一个完整的后端解决方案,我们提供轻量级的SDK开发包,让开发者以最小的配置和最简单的方式使用Bmob平台提供的服务,进而完全消除开发者编写服务器代码以及维护服务器的操作。

Bmob致力于为开发者提供快速开发服务,为方便大家更好的理解BmobSDK能够做的事情,我们特意为大家提供了一些源码,大家可以下载之后,嵌入Bmob的AppKey,再打包运行。

阅读源码是一种良好的习惯!!

在Bmob平台注册后,每个账户可创建多个应用程序,创建的每个应用程序都有其独自的应用程序ID,此后所有的应用程序将凭其ID进行BmobSDK的使用。即使只有一个应用程序,也可以以不同的版本进行测试和生产。

目前为止,我们支持的数据类型有String、Integer、Boolean、ArrayList以及BmobObject对象类型。同时Bmob也支持BmobDate、BmobGeoPoint、BmobFile数据类型。

一个对象对应了数据表中的一条数据,也可以理解为应用程序中的JavaBean.

publicclassGameScoreextendsBmobObject{privateStringplayerName;privateIntegerscore;privateBooleancheatMode;privateBmobFilepic;publicStringgetPlayerName(){returnplayerName;}publicvoidsetPlayerName(StringplayerName){this.playerName=playerName;}publicIntegergetScore(){returnscore;}publicvoidsetScore(Integerscore){this.score=score;}publicBooleangetCheatMode(){returncheatMode;}publicvoidsetCheatMode(BooleancheatMode){this.cheatMode=cheatMode;}publicBmobFilegetPic(){returnpic;}publicvoidsetPic(BmobFilepic){this.pic=pic;}}类名和表名的关系//这时候实际操作的表是T_a_bpublicclassGameScoreextendsBmobObject{privateStringplayerName;privateIntegerscore;privateBooleancheatMode;privateBmobFilepic;publicGameScore(){this.setTableName("T_a_b");}publicStringgetPlayerName(){returnplayerName;}//其他方法,见上面的代码}当然了,你也可以在GameScore实例中动态调用setTableName方法,实现操作可变表(如根据日期建立表来存储信息)的可能。

如果您使用了setTableName方法来自定义表名,那么在对该表进行数据查询的时候必须使用以下方法来进行查询。需要注意的是查询的结果是一个JSONArray,您需要自行解析JSONArray中的数据来进行使用。

添加数据非常简单,任何BmobObject对象都具有save方法可以用于将当前对象的内容保存到服务端。例如,你现在要保存一条游戏分数的记录,可以这样做:

GameScoregameScore=newGameScore();gameScore.setPlayerName("Barbie");gameScore.setScore(89);gameScore.setCheatMode(false);gameScore.save(mContext,newSaveListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("添加数据成功,返回objectId为:"+gameScore.getObjectId());}@OverridepublicvoidonFailure(intcode,Stringarg0){//TODOAuto-generatedmethodstub//添加失败}});运行完以上代码后,数据即可保存到服务器端。为了确认数据是否真的已经保存成功,你可以在Bmob服务器端你应用程序的数据浏览项目中进行查看。你应该看到类似这样的结果:

objectId:"0c6db13c",score:89,playerName:"Barbie",cheatMode:false,createdAt:"2013-09-2710:32:54",updatedAt:"2013-09-2710:32:54"注:

数据的查询可能是每个应用都会频繁使用到的,BmobSDK中提供了BmobQuery类,它提供了多样的方法来实现不同条件的查询,同时它的使用也是非常的简单和方便的。

查询某个数据表中的所有数据是非常简单的查询操作,例如:查询所有人员的信息。

BmobQueryquery=newBmobQuery();query.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});怎么样,是不是很简单,而且查询的结果不需要进行任何处理,BmobSDK已经为你封装成相应的JavaBean集合了,你直接使用即可。

当我们知道某条数据的objectId时,就可以根据objectId直接获取单条数据对象。例如:查询objectId为a203eba875的人员信息。

BmobQueryquery=newBmobQuery();query.getObject(this,"a203eba875",newGetListener(){@OverridepublicvoidonSuccess(GameScoreobject){//TODOAuto-generatedmethodstubtoast("查询成功:");}@OverridepublicvoidonFailure(intcode,Stringarg0){//TODOAuto-generatedmethodstubtoast("查询失败:"+arg0);}});条件查询在查询的使用过程中,基于不同条件的查询是非常常见的,BmobQuery同样也支持不同条件的查询。

例如:如果要过滤掉特定键的值可以使用addWhereNotEqualTo方法。比如需要查询playerName不等于“Barbie”的数据时可以这样写:

query.addWhereNotEqualTo("playerName","Barbie");当然,你可以在你的查询操作中添加多个约束条件,来查询符合要求的数据。

query.addWhereNotEqualTo("playerName","Barbie");//名字不等于Barbiequery.addWhereGreaterThan("score",60);//条件:分数大于60岁各种不同条件的比较查询:

//分数<50query.addWhereLessThan("score",50);//分数<=50query.addWhereLessThanOrEqualTo("score",50);//分数>50query.addWhereGreaterThan("score",50);//分数>=50query.addWhereGreaterThanOrEqualTo("score",50);如果你想查询匹配几个不同值的数据,如:要查询“Barbie”,“Joe”,“Julia”三个人的成绩时,你可以使用addWhereContainedIn方法来实现。

String[]names={"Barbie","Joe","Julia"};query.addWhereContainedIn("playerName",Arrays.asList(names));相反,如果你想查询排除“Barbie”,“Joe”,“Julia”这三个人的其他同学的信息,你可以使用addWhereNotContainedIn方法来实现。

比如,你想查询2015年2月11号之前的Person数据,那么可以使用addWhereLessThan或者addWhereLessThanOrEqualTo(包含当天)来查询。如果想查询之后的数据,则可以使用addWhereGreaterThan或addWhereGreaterThanOrEqualTo(包含当天)来查询。

BmobQueryquery=newBmobQuery("Person");StringdateString="2015-02-11";SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");Datedate=null;try{date=sdf.parse(dateString);}catch(ParseExceptione){e.printStackTrace();}//这是查询2015年2月11之前的Person数据query.addWhereLessThan("createdAt",newBmobDate(date));//这是查询2015年2月11之后的Person数据//query.addWhereGreaterThan("createdAt",newBmobDate(date));```java###模糊查询如果你想实现类似数据库的模糊查询,比如,你想查询用户表中用户名中含有“a”的用户,那么你可以使用`addWhereContains`方法来实现。```javaStringvalue="a";query.addWhereContains("username",value);分页查询有时,在数据比较多的情况下,你希望查询出的符合要求的所有数据能按照多少条为一页来显示,这时可以使用setLimit方法来限制查询结果的数据条数来进行分页。默认情况下,Limit的值为10,最大有效设置值1000(设置的数值超过1000还是视为1000)。

query.setLimit(10);//限制最多10条数据结果作为一页在数据较多的情况下,在setLimit的基础上分页显示数据是比较合理的解决办法,setSKip方法可以做到跳过查询的前多少条数据来实现分页查询的功能。默认情况下Skip的值为10。

对应数据的排序,如数字或字符串,你可以使用升序或降序的方式来控制查询数据的结果顺序:

//根据score字段升序显示数据query.order("score");//根据score字段降序显示数据query.order("-score");//多个排序字段可以用(,)号分隔query.order("-score,createdAt");说明:多个字段排序时,先按第一个字段进行排序,再按第二个字段进行排序,依次进行。

如果你只是想统计满足查询对象的数量,你并不需要获取所有匹配对象的具体数据信息,可以直接使用count替代findObjects。例如,查询一个特定玩家玩的游戏场数:

BmobQueryquery=newBmobQuery();query.addWhereEqualTo("playerName","Barbie");query.count(this,GameSauce.class,newCountListener(){@OverridepublicvoidonSuccess(intcount){//TODOAuto-generatedmethodstubtoast("Barbiehasplayed"+count+"games");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("countfailure:"+msg);}});复杂查询复合与查询(and)有些查询需要使用到复合“与”的查询条件,例如:你想查询出Person表中年龄在6-29岁之间且姓名以"y"或者"e"结尾的人,那么,可以采用and查询,示例代码如下:

BmobQueryeq1=newBmobQuery();eq1.addWhereEqualTo("age",29);BmobQueryeq2=newBmobQuery();eq2.addWhereEqualTo("age",6);List>queries=newArrayList>();queries.add(eq1);queries.add(eq2);BmobQuerymainQuery=newBmobQuery();mainQuery.or(queries);mainQuery.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstub}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstub}});你还可以在此基础上添加更多的约束条件到新创建的BmobQuery对象上,表示一个and查询操作。

如果你要获得某个字段匹配特定BmobObject的对象列表,你可以像查询其他数据类型一样使用addWhereEqualTo来查询。例如:每个Weibo对象都包含一个BmobUser对象在它的author字段上,现在你想查询当前用户发布的所有微博信息,如下:

query.include("weibo.author");这里需要注意的是:

1、include的查询对象只能为BmobPointer类型,而不能是BmobRelation类型。

2、如果你想include两个对象,你可以这样做:

query.include("Comment,User");但不能如下的做法:

query.include("Comment");query.include("User");缓存查询缓存查询通常是将查询结果缓存在磁盘上。当用户的设备处于离线状态时,就可以从缓存中获取数据来显示。或者在应用界面刚刚启动,从网络获取数据还未得到结果时,先使用缓存数据来显示。这样可以让用户不必在按下某个按钮后进行枯燥的等待。默认的查询操作是没有启用缓存的,开发者可以使用setCachePolicy方法来启用缓存功能。例如:优先从缓存获取数据,如果获取失败再从网络获取数据。

bmobQuery.setCachePolicy(CachePolicy.CACHE_ELSE_NETWORK);//先从缓存获取数据,如果没有,再从网络获取。bmobQuery.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});BmobSDK提供了几种不同的缓存策略,以适应不同应用场景的需求:

只从网络获取数据,且不会将数据缓存在本地,这是默认的缓存策略。

只从缓存读取数据,如果缓存没有数据会导致一个BmobException,可以忽略不处理这个BmobException.

只从网络获取数据,同时会在本地缓存数据。

先从缓存读取数据,如果没有,再从网络获取。

先从缓存取数据,无论结果如何都会再次从网络获取数据。也就是说会产生2次调用。通常的用法是先快速取出缓存数据展示view,然后再后台连接网络取得最新数据,取到后用来自网络服务器的最新数据更新view。

如果需要操作缓存内容,可以使用BmobQuery提供的方法做如下操作:

有的时候,一张表的数据列比较多,而我们只想查询返回某些列的数据时,我们可以使用BmobQuery对象提供的addQueryKeys方法来实现。如下所示:

BmobQuerybmobQuery=newBmobQuery();bmobQuery.addQueryKeys("objectId");bmobQuery.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");//注意:这里的Person对象中只有指定列的数据。}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});指定多列时用,号分隔每列,如:addQueryKeys("objectId,name,add");

更新一个对象也是非常简单。例如:将GameScore表中objectId为0c6db13c的游戏分数修改为77.

GameScoregameScore=newGameScore();gameScore.setScore(77);gameScore.update(this,"0c6db13c",newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("更新成功:");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("更新失败:"+msg);}});删除数据从服务器删除对象。例如:将GameScore表中objectId为dd8e6aff28的数据删除。

GameScoregameScore=newGameScore();gameScore.setObjectId("dd8e6aff28");gameScore.delete(this,newDeleteListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("删除成功");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("删除失败:"+msg);}});删除字段你可以在一个对象中删除一个字段,通过remove操作:

GameScoregameScore=newGameScore();gameScore.setObjectId("dd8e6aff28");gameScore.remove("score");//删除GameScore对象中的score字段gameScore.update(this,newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("删除GameScore对象中的score字段成功");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("删除GameScore对象中的score字段失败:"+msg);}});数组对于数组型数据,BmobSDK提供了3种操作来原子性地更改一个数组字段:add、addAll在一个数组字段的后面添加一些指定的对象(包装在一个数组内)addUnique、addAllUnique只会在原本数组字段中没有这些对象的情形下才会添加入数组,插入数组的位置不固定的removeAll从一个数组字段的值内移除指定的数组中的所有对象

给一个数据对象中的数组类型字段添加数据可以使用以下方法添加:

Personp=newPerson();p.add("hobby","唱歌");//添加一个值到hobby字段中,hobby为数组类型//p.addAll("hobby",Arrays.asList("游泳","看书"));//一次添加多个值到hobby字段中p.save(this,newSaveListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("保存成功");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("保存失败:"+msg);}});更新数组数据举个例子,hobby(爱好)是一个数组类型的字段,那么我们可以在hobby字段中加入一些爱好,只有在hobby字段中不包含这些爱好的情况下才会被加入:

Personp=newPerson();p.setObjectId("d32143db92");p.addUnique("hobby","爬山");//添加一个值到hobby字段中//p.addAllUnique("hobby",Arrays.asList("游泳","羽毛球"));//一次添加多个值到hobby字段中p2.update(this,newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("更新爱好成功");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("更新爱好失败:"+msg);}});查询数组数据对于字段类型为数组的情况,可以查找字段中的数组值包含有xxx的对象:

BmobQueryquery=newBmobQuery();String[]hobby={"阅读","唱歌"};query.addWhereContainsAll("hobby",Arrays.asList(hobby));query.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+code);}});删除数组数据同理我们也可以使用removeAll从数组字段中移除某些值:

由于关联关系讲解起来比较复杂,以下用一个简单的案例来说明在Bmob中是如何使用关联关系的,最后会提供相应的源码。这个场景是这样的:我们生活中每个人都可能会办理多张银行卡,而每张银行卡的登记人只有一个。从这个场景可以看出有两个对象,一个是人,一个是银行卡。

我们接下来需要在Web端创建对应的表,分别是用户表和银行卡表,其中用户表我们直接使用Bmob提供的系统表User表。在创建数据表的字段的时候,当选择字段类型为Pointer或Relation时,会提示你选择该字段所指向或关联的数据表。如下图所示:

根据本案例的场景,我们需要在User表中多增加一列为cards,数据类型为Relation,然后创建一个银行卡信息表(BankCard),银行卡表的主要结构如下:bankNameString银行名称cardNumberString银行卡号userPointer<_User>银行卡用户

为了更直观的展示数据表的结构,我将两个表的截图贴上,以供参考:

用户表(注意cards字段)

银行卡表(注意user字段)

接下来我们需要创建User表和BankCard表对应的数据对象,User表对应的数据对象的代码如下:

BankCard表对应的数据对象的代码如下:

publicclassBankCardextendsBmobObject{/***银行卡号*/privateStringcardNumber;/***银行名称*/privateStringbankName;/***户主*/privateMyUseruser;publicStringgetCardNumber(){returncardNumber;}publicvoidsetCardNumber(StringcardNumber){this.cardNumber=cardNumber;}publicStringgetBankName(){returnbankName;}publicvoidsetBankName(StringbankName){this.bankName=bankName;}publicMyUsergetUser(){returnuser;}publicvoidsetUser(MyUseruser){this.user=user;}}这里需要注意的是:1、类名要和表名保持一致。2、MyUser属性对应为Pointer的指针类型。

接下来我们就从代码层次上来讲解,怎么样来操作这些关联关系的数据。首先我们来讲添加关联关系。在我们创建一张银行卡信息时,需要指定这张卡的户主(user),这就是添加的一对一的关联关系。代码如下:

/***创建一条银行卡信息到BankCard表中,并关联到用户的银行卡信息中*@parambankName银行名称*@paramcardNumber银行卡号*/privatevoidsaveBankCardInfo(StringbankName,StringcardNumber){if(TextUtils.isEmpty(user.getObjectId())){toast("当前用户的object为空");return;}card=newBankCard();card.setBankName(bankName);//设置银行名称card.setCardNumber(cardNumber);//设置银行卡号card.setUser(user);//设置银行卡户主card.save(this,newSaveListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("成功保存一条银行卡信息到BankCard表中");addCardToUser();}@OverridepublicvoidonFailure(intarg0,Stringarg1){//TODOAuto-generatedmethodstubtoast("很遗憾,保存一条银行卡信息到BankCard表中失败了");}});}修改关联关系当我们的这张银行卡创建成功后,不仅仅只是设置银行卡的户主就可以来,我们还需要更新户主的信息,也就是将当前银行卡关联到用户的cards列中。这就是修改关联关系,代码如下:

/***添加银行卡到用户的银行卡信息中*/privatevoidaddCardToUser(){if(TextUtils.isEmpty(user.getObjectId())||TextUtils.isEmpty(card.getObjectId())){toast("当前用户或者当前Card对象的object为空");return;}BmobRelationcards=newBmobRelation();cards.add(card);user.setCards(cards);user.update(this,newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("已成功添加到用户的银行卡信息中");}@OverridepublicvoidonFailure(intarg0,Stringarg1){//TODOAuto-generatedmethodstubtoast("很遗憾,用户的银行卡信息添加失败");}});}上面的代码将某银行卡添加到了用户的银行卡信息中,还有一种情况是从用户的银行卡信息中删除掉某银行卡的信息,在现实生活中我叫注销我的银行卡。代码示例如下:

/***删除用户信息中的某银行卡信息*/privatevoidremoveCardToUser(){if(TextUtils.isEmpty(user.getObjectId())||TextUtils.isEmpty(card.getObjectId())){toast("当前用户或者当前Card对象的object为空");return;}BmobRelationcards=newBmobRelation();cards.remove(card);user.setCards(cards);user.update(this,newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("在用户信息中已成功移除该银行卡信息");}@OverridepublicvoidonFailure(intarg0,Stringarg1){//TODOAuto-generatedmethodstubtoast("很遗憾,移除失败");}});}查询关联关系需求1:查询我的所有银行卡信息,代码如下:

/***查询我的所有银行卡信息*/privatevoidfindMyCards(){BmobQuerycards=newBmobQuery();/***注意这里的查询条件*第一个参数:是User表中的cards字段名*第二个参数:是指向User表中的某个用户的BmobPo*er对象*/cards.addWhereRelatedTo("cards",newBmobPointer(user));cards.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listarg0){//TODOAuto-generatedmethodstubtoast("我现在有"+arg0.size()+"张银行卡");for(BankCardbankCard:arg0){Log.d("bmob","objectId:"+bankCard.getObjectId()+",银行名称:"+bankCard.getBankName()+",卡号:"+bankCard.getCardNumber());}}@OverridepublicvoidonError(intarg0,Stringarg1){//TODOAuto-generatedmethodstubtoast("查询我银行卡信息失败");}});}需求2:查询银行卡信息时同时获取该卡的户主信息,代码如下:

在BmobObject对象中提供了三种用于批量操作的方法,分别是insertBatch、updateBatch、deleteBatch,批量添加、更新、删除。

很多应用可能会有计数器功能的需求(并发请求会出现这个问题),比如某条信息被点赞多少次,如果多人同时操作,如果用普通的更新方法的话,可能会导致数据不一致的情况。为此,Bmob提供了原子计数器来保证原子性的修改某一数值字段的值。注意:原子计数器只能对应用于Web后台的Number字段,和实体类实现中的Integer对象类型(类中请不要用int类型)。

gameScore.increment("score");//分数递增1gameScore.update(this,updateListener);您还可以通过increment(key,amount)方法来递增或递减任意幅度的数字

创建文件对象方式如下:

StringpicPath="sdcard/temp.jpg";BmobFilebmobFile=newBmobFile(newFile(picPath));上传单一文件文件分片上传的方法非常简单,示例代码如下:

StringpicPath="sdcard/temp.jpg";BmobFilebmobFile=newBmobFile(newFile(picPath));bmobFile.uploadblock(this,newUploadFileListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstub//bmobFile.getUrl()---返回的上传文件的地址(不带域名)//bmobFile.getFileUrl(context)--返回的上传文件的完整地址(带域名)toast("上传文件成功:"+bmobFile.getFileUrl(context));}@OverridepublicvoidonProgress(Integervalue){//TODOAuto-generatedmethodstub//返回的上传进度(百分比)}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("上传文件失败:"+msg);}});批量上传文件BmobSDK_V3.2.7新增批量上传文件的方法,使用起来也很简单,示例代码如下:

bmobQuery.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");for(Personperson:object){if(person.getPic()!=null){//文件名称person.getPic().getFilename();//文件下载地址person.getPic().getFileUrl();}}}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});删除文件BmobSDKV3.3.0提供了删除文件的接口,方便开发者对文件进行管理,示例代码如下:

注:

1、单个文件上传大小不可超过200M;

2、文件分片上传的大小不可超过200M;

3、有时候使用upload方式上传不超过10M的文件的时候会出现OOM异常,故,建议开发者使用uploadblock(分片上传)方法来上传文件。

4、文件的批量上传是BmobSDK_v3.2.7版本才提供的功能,如需使用,请更新版本。

1、获取缩略图

如果你的BmobFile对象是保存的图片类型的文件,那么当你需要使用缩略图功能的时候,可以使用loadImageThumbnail方法来获取改图片的缩略图。

bmobFile.loadImageThumbnail(this,imageView,300,300);你还可以指定获取缩略图的图片质量

bmobFile.loadImageThumbnail(this,imageView,300,300,100);2、获取图片

很多时候您可能只是想直接加载图片来显示,那么你可以使用loadImage方法来加载原图。

bmobFile.loadImage(this,imageView);同样您也可以指定加载原图显示的大小

bmobFile.loadImage(this,imageView,300,300);3、缩略图的案例源码

新版文件管理是通过BmobProFile类(自BmobSDKv3.2.9开始)完成的,其提供了文件的单一上传、批量上传、文件下载、生成缩略图等功能,

BmobProFile和BmobFile两者之间是不兼容的,也就是说不能用BmobFile类上传的成功后得到的文件名再用BmobProFile类提供的下载方法来下载。

单一文件上传只需要调用BmobProFile类提供的静态方法:upload,示例代码如下:

BTPFileResponseresponse=BmobProFile.getInstance(MainActivity.this).upload(filePath,newUploadListener(){@OverridepublicvoidonSuccess(StringfileName,Stringurl){//TODOAuto-generatedmethodstubdialog.dismiss();showToast("文件已上传成功:"+fileName);}@OverridepublicvoidonProgress(intratio){//TODOAuto-generatedmethodstubBmobLog.i("MainActivity-onProgress:"+ratio);}@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubshowToast("上传出错:"+errormsg);}});onSuccess方法参数:

1、fileName:文件名(带后缀),这个文件名是唯一的,开发者需要记录下该文件名,方便后续下载该文件。

2、url:文件服务器地址(如果你上传的是图片类型的文件,此url地址并不能直接在浏览器查看(会出现404错误),需要经过URL签名得到真正的可访问的URL地址)。

1、使用场景:

开发者上传的如果是图片且希望能够访问完整的URL地址用来客户端直接显示图片,那么就需要用到URL签名。

2、签名认证步骤:

1)、开启签名认证:

开发者需要在web后台开启文件管理的URL签名认证:

文件管理-->基本配置-->设置SecretKey-->开启-->保存

注:此处的secretKey可任意填写,它是专门针对文件服务的,和"应用密钥"中的数据服务使用到的SecretKey是不一样的。

此部分为配置了URL的签名认证安全的开发者使用,若没配置,则按照正常处理。

2)、URL签名说明:

开启签名认证的URL地址格式:

未开启签名认证的URL地址格式:

URL=url(文件上传成功之后返回的url地址)t=(客户端类型)&a=(应用密钥中的AccessKey)

1、t:客户端类型(1~19代表SDK客户端,1:IOS,2:Android,3:wp,…,20:官网后台;21:其他网站)

2、AccessKey:在web后台的应用密钥中查看

4、Token:Token签名使用了web后台的文件管理中设置的SecretKey,开发者要注意此值的安全不被泄漏.

3)、URL签名步骤:

请求的文件名称fileName:dfwsdweqe0012.jpg;

假如请求参数为:

当前客户端类型:t=1//注释:Android

App的AccessKey:a=b63737a2825821fc3208b8a80a524da

当前的密钥SecretKey:abcdefg

组装请求URI:

Uri=/dfwsdweqe0012.jpgt=1&a=b63737a2825821fc3208b8a80a524da&e=1415697363

得到Token:

1、针对Uri进行HMAC-SHA1算法签名;

2、对签名后的字符串进行URL安全Base64编码;

3、编码后即为要要发送的token。

伪代码如下:

Token=urlbase64_encode(hmacsha1(Uri,secretKey));

得到最终的发送请求的URL为:

注:1、以上所有的参数名(t,a,e,token)均为小写,参数顺序为t,a,e,token,uri、secretkey等编码格式都为utf-8。

2、URL安全的Base64编码方式的基本过程是先将内容以Base64格式编码为字符串,然后检查该编码后的字符串,将字符串中的加号+换成中划线-,斜杠/换成下划线_,得到最终的字符串;

4)、URL签名方法:

鉴于URL签名比较复杂,BmobSDKV3.3.0的BmobProFile类为开发者提供了获取URL签名的方法:signURL(V3.3.2已修改为BmobProFile类的内部方法)

/***@paramfileName:文件名*@paramfileUrl:文件url地址*@paramaccessKey:web应用密钥中的AccessKey*@parameffectTime:有效时长(秒)*@paramsecretKey:密钥*@return可访问的URL地址*/StringURL=BmobProFile.getInstance(MainActivity.this).signURL(StringfileName,StringfileUrl,StringaccessKey,longeffectTime,StringsecretKey)未开启URL签名认证的示例代码如下:

1、fileName/fileUrl:表示上传(批量上传)成功后得到的文件名/文件服务器地址。

2、effectTime:表示这个URL请求的有效时长,单位为秒,一旦超过有效时长,则该URL请求失效。

3、若开发者未开启URL签名认证,则前三个参数必填,后面的effectTime传0,secretKey传null即可。

4、若文件类型为图片类型,客户端需要直接显示的话,则不建议开启URL签名认证

BmobProFile同样提供了批量上传文件的静态方法:uploadBatch:示例代码如下:

BmobProFile.getInstance(MainActivity.this).uploadBatch(files,newUploadBatchListener(){@OverridepublicvoidonSuccess(booleanisFinish,String[]fileNames,String[]urls){//TODOAuto-generatedmethodstubif(isFinish){dialog.dismiss();}showToast(""+isFinish+"-----"+Arrays.asList(fileNames)+"----"+Arrays.asList(urls));}@OverridepublicvoidonProgress(intcurIndex,intcurPercent,inttotal,inttotalPercent){//TODOAuto-generatedmethodstubdialog.setProgress(curIndex);BmobLog.i("MainActivity-onProgress:"+curIndex+"---"+curPercent+"---"+total+"----"+totalPercent);}@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubdialog.dismiss();showToast("批量上传出错:"+statuscode+"--"+errormsg);}});}onProgress方法参数:

1、curIndex:表示当前第几个文件正在上传

2、curPercent:表示当前上传文件的进度值(百分比)

3、total:表示总的上传文件数

4、totalPercent:表示总的上传进度(百分比)

BmobProFile同样提供了文件下载的静态方法:download,只需要将上传文件后记录下来的文件名fileName(必须是通过BmobProFile类的upload方法得到的)作为参数即可,示例代码如下:

BmobProFile.getInstance(MainActivity.this).download(fileName,newDownloadListener(){@OverridepublicvoidonSuccess(StringfullPath){//TODOAuto-generatedmethodstubshowToast("下载成功:"+fullPath);}@OverridepublicvoidonProgress(StringlocalPath,intpercent){//TODOAuto-generatedmethodstubBmobLog.i("MainActivity-download-->onProgress:"+percent);dialog.setProgress(percent);}@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubdialog.dismiss();showToast("下载出错:"+statuscode+"--"+errormsg);}});注:

1、onProgress参数localPath:表示当前下载文件的地址,当下载进度不为100的时候,这个地址下面的文件是不完整的,只有一部分。

2、onSuccess参数fullPath:表示下载成功后文件的存储完整地址,和localpath的路径是一样的。

3、允许开发者自定义保存下载文件的目录名,可在Apllication中对其进行初始化配置。示例如下:

BmobConfigurationconfig=newBmobConfiguration.Builder(context).customExternalCacheDir("目录名").build();BmobPro.getInstance(context).initConfig(config);缩略图处理对图片进行缩略图处理,BmobProFile类提供了两种方式:

一种将生成缩略图的任务提交给服务器,由服务器来处理并同步返回生成后的服务器缩略图地址(submitThumnailTask);另一种是SDK提供的本地处理缩略图的方法(getLocalThumbnail)。

一、submitThumnailTask

示例代码如下:

BmobProFile.getInstance(MainActivity.this).submitThumnailTask(fileName,modelId,newThumbnailListener(){@OverridepublicvoidonSuccess(StringthumbnailName,StringthumbnailUrl){//TODOAuto-generatedmethodstub//此处得到的缩略图地址(thumbnailUrl)不一定能够请求的到,此方法为异步方法BmobLog.i("MainActivity-onSuccess:"+thumbnailName+"-->"+thumbnailUrl);}@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubBmobLog.i("MainActivity-onError:"+statuscode+"---"+errormsg);}});注:

A、请求参数:fileName:文件名,modelId:缩略图的规格类型ID

B、thumbnailName的格式:

fileName+"_"+modelId

如果fileName=f24af10cbc15476e9789afaf168c3b8e.jpg,modelId=1,那么thumbnailName=f24af10cbc15476e9789afaf168c3b8e.jpg_1。

C、目前Bmob提供的规格类型ID(modelId)有六种:

1--指定宽,高自适应,等比例缩放;

2--指定高,宽自适应,等比例缩放;

3--指定最长边,短边自适应,等比例缩放;

4--指定最短边,长边自适应,等比例缩放;

5--指定最大宽高,等比例缩放;

6--固定宽高,居中裁剪;

二、getLocalThumbnail

SDK提供了三种处理本地缩略图的方式:

一、指定规格ID

BmobProFile.getInstance(LocalThumbnailActivity.this).getLocalThumbnail(localPath,modelId,newLocalThumbnailListener(){@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubBmobLog.i("MainActivity-localThumbnail-->生成缩略图失败:"+statuscode+","+errormsg);}@OverridepublicvoidonSuccess(StringthumbnailPath){//TODOAuto-generatedmethodstubBmobLog.i("MainActivity-localThumbnail-->生成后的缩略图路径:"+thumbnailPath);}});二、指定规格ID、宽、高

BmobProFile.getInstance(LocalThumbnailActivity.this).getLocalThumbnail(localPath,modeId,width,height,newLocalThumbnailListener(){@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubshowToast("本地缩略图创建失败:"+statuscode+","+errormsg);}@OverridepublicvoidonSuccess(StringthumbnailPath){//TODOAuto-generatedmethodstubshowToast("本地缩略图创建成功:"+thumbnailPath);}});三、指定规格ID、宽、高、图片压缩质量

为了方便开发者对图片进行压缩处理,V3.3.3版本在获取本地缩略图的方法中新增了图片压缩质量(quality)参数,取值范围:0-100。示例代码如下:

BmobProFile.getInstance(LocalThumbnailActivity.this).getLocalThumbnail(localPath,modeId,width,height,quality,newLocalThumbnailListener(){@OverridepublicvoidonError(intstatuscode,Stringerrormsg){//TODOAuto-generatedmethodstubshowToast("本地缩略图创建失败:"+statuscode+","+errormsg);}@OverridepublicvoidonSuccess(StringthumbnailPath){//TODOAuto-generatedmethodstubshowToast("本地缩略图创建成功:"+thumbnailPath);}});注:

1、localPath:图片的本地路径,需要带后缀名

2、modelId:开发者应事先在应用管理后台(文件管理-->自定义版本-->缩略图配置版本)完成基本的生成缩略图的规格配置:

数据实时同步是一个超酷的功能!

SDK可以实现对数据表或行的监听,当这个表或者行的数据发生变化时,Bmob会立即将变化的信息告知SDK。这种服务非常适合做游戏开发(如,开发斗地主游戏,三个人同时监听一行数据的变化,任何一个人出牌都会将数据写入到这行数据中,其他人也就立即知道了)、群聊(一群人监听某个表的变化,任何人发言都会将数据写入到这个表中,其他人也可以立即知道了)等实时性要求很高的场景中。

使用数据实时功能,首先需要创建BmobRealTimeData对象,然后调用start方法连接服务器。

BmobRealTimeDatartd=newBmobRealTimeData();rtd.start(this,newValueEventListener(){@OverridepublicvoidonDataChange(JSONObjectdata){//TODOAuto-generatedmethodstubLog.d("bmob","("+data.optString("action")+")"+"数据:"+data);}@OverridepublicvoidonConnectCompleted(){//TODOAuto-generatedmethodstubLog.d("bmob","连接成功:"+rtd.isConnected());}});start方法中的ValueEventListener参数用于监听连接成功和数据变化的回调。当有数据变化时会通过onDataChange回调方法反馈到客户端。开发者只需要处理得到的data就可以了。

1、监听器不支持UI线程,在监听回调中请不要直接操作UI;

2、如果你要监听User、Installation等系统表的话,表名前需要加上“_”,例如:_User

在BmobRealTimeData对象连接成功后,就可以进行数据的监听了。BmobSDK提供了监听表和行的方法如下:

//监听表更新rtd.subTableUpdate(tableName);//监听表删除rtd.subTableDelete(tableName);//监听行更新rtd.subRowUpdate(tableName,objectId);//监听行删除rtd.subRowDelete(tableName,objectId);其中tableName为要监听的数据表名,objectId为要监听的数据行Id,通常比较保险的做法是在BmobRealTimeData对象的连接状态为true的情况下进行监听,代码如下:

if(rtd.isConnected()){//监听表更新rtd.subTableUpdate(tableName);}取消监听当开发者想取消监听某个行为是,可使用下面的方法:

//取消监听表更新rtd.unsubTableUpdate(testTableName);//取消监听表删除rtd.unsubTableDelete(testTableName);//取消监听行更新rtd.unsubRowUpdate(testTableName,objectId);//取消监听行删除rtd.unsubRowDelete(testTableName,objectId);用户管理用户是一个应用程序的核心。对于个人开发者来说,自己的应用程序积累到越多的用户,就会给自己带来越强的创作动力。因此Bmob提供了一个专门的用户类——BmobUser来自动处理用户账户管理所需的功能。

有了这个类,你就可以在你的应用程序中添加用户账户功能。

BmobUser除了从BmobObject继承的属性外,还有几个特定的属性:username:用户的用户名(必需)。password:用户的密码(必需)。email:用户的电子邮件地址(可选)。

很多时候,你的用户表还会有很多其他字段,如性别、年龄、头像等。那么,你需要对BmobUser类进行扩展,添加一些新的属性。示例代码如下所示:

publicclassSpecialUserextendsBmobUser{privatebooleansex;privateStringnick;publicbooleangetSex(){returnthis.sex;}publicvoidsetSex(booleansex){this.sex=sex;}publicStringgetNick(){returnthis.sex;}publicvoidsetNick(Stringnick){this.nick=nick;}}更多代码实现大家可以下载SDK,在里面的BmobExample中查找MyUser类,参考它的用法。

创建用户对象如下:

BmobUseruser=newBmobUser();注册用户你的应用程序可能会要求用户注册。下面的代码是一个典型的注册过程:

BmobUserbu=newBmobUser();bu.setUsername("sendi");bu.setPassword("123456");bu.setEmail("sendi@163.com");bu.signUp(this,newSaveListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("注册成功:");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("注册失败:"+msg);}});在注册过程中,服务器会对注册用户信息进行检查,以确保注册的用户名和电子邮件地址是独一无二的。此外,对于用户的密码,你可以在应用程序中进行相应的加密处理后提交。

如果注册不成功,你可以查看返回的错误对象。最有可能的情况是,用户名或电子邮件已经被另一个用户注册。这种情况你可以提示用户,要求他们尝试使用不同的用户名进行注册。

你也可以要求用户使用Email做为用户名注册,这样做的好处是,你在提交信息的时候可以将输入的“用户名“默认设置为用户的Email地址,以后在用户忘记密码的情况下可以使用Bmob提供重置密码功能。

这里有两点需要注意的:

BmobUser.logOut(this);//清除缓存用户对象BmobUsercurrentUser=BmobUser.getCurrentUser(this);//现在的currentUser是null了更新用户很多情况下你可能需要修改用户信息,比如你的应用具备修改个人资料的功能,Bmob提供的用户更新方式有两种写法:

第一种:新建一个用户对象,并调用update(context,objectId,updateListener)方法来更新(推荐使用),示例:

BmobUsernewUser=newBmobUser();newUser.setEmail("xxx@163.com");BmobUserbmobUser=BmobUser.getCurrentUser(this);newUser.update(this,bmobUser.getObjectId(),newUpdateListener(){@OverridepublicvoidonSuccess(){//TODOAuto-generatedmethodstubtoast("更新用户信息成功:");}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("更新用户信息失败:"+msg);}});第二种:获取本地的用户对象,并调用update(context,updateListener)方法来更新(不推荐使用),示例:

查询用户和查询普通对象一样,只需指定BmobUser类即可,如下:

BmobQueryquery=newBmobQuery();query.addWhereEqualTo("username","lucky");query.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询用户成功:"+object.size());}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询用户失败:"+msg);}});浏览器中查看用户表

User表是一个特殊的表,专门存储BmobUser对象。在浏览器端,你会看到一个User表旁边有一个小人的图标。

一旦你引入了一个密码系统,那么肯定会有用户忘记密码的情况。对于这种情况,我们提供了一种方法,让用户安全地重置起密码。

重置密码的流程很简单,开发者只需要求用户输入注册的电子邮件地址即可:

为方便大家了解如何用Bmob开发找回密码的功能,我们为大家准备了另外一份文档,详细见我们在Github中的文档:

emailVerified字段有3种状态可以考虑:

{"qq":{"openid":"AAC61872C459FB196AECFA9D6FEBA334","access_token":"19A1E9FB3E440B4D15DBB44a39946FD4","expires_in":7776000}}解除绑定解除第三方账号与BmobUser的绑定关系如下代码所示:

其中,最灵活的方法是通过ACL和角色,它的思路是每一条数据有一个用户和角色的列表,以及这些用户和角色拥有什么样的许可权限。

大多数应用程序需要对不同的数据进行灵活的访问和控制,这就可以使用Bmob提供的ACL模式来实现。例如:

用BmobSDK,你可以对这些数据设置一个默认的ACL,这样,即使黑客反编译了你的应用,获取到ApplicationKey,也仍然无法操作和破坏你的用户数据,确保了用户数据的安全可靠。而作为开发者,当你需要对这些数据进行管理时,可以通过超级权限Key(MasterKey)进行。

在没有显示指定的情况下,每一个BmobObject(表)中的ACL(列)属性的默认值是所有人可读可写的。在客户端想要修改这个权限设置,只需要简单调用BmobACL的setPublicReadAccess方法和setPublicWriteAccess方法,即:

BmobACLaCL=newBmobACL();aCL.setPublicReadAccess(true);aCL.setPublicWriteAccess(true);注意:可读可写是默认的权限,不需要写额外的代码。

Blogblog=newBlog();blog.setTitle("论电影的七个元素");blog.setContent("这是blog的具体内容");BmobACLacl=newBmobACL();//创建一个ACL对象acl.setPublicReadAccess(true);//设置所有人可读的权限acl.setWriteAccess(BmobUser.getCurrentUser(this),true);//设置当前用户可写的权限blog.setACL(acl);//设置这条数据的ACL信息blog.save(this,newSaveListener(){@OverridepublicvoidonSuccess(){//添加成功}@OverridepublicvoidonFailure(intcode,Stringmsg){//添加失败}});有时,用户想发表一篇不公开的日志,这种情况只有发布者才对这篇日志拥有读写权限,相应的代码如下:

Blogblog=newBlog();blog.setTitle("一个人的秘密");blog.setContent("这是blog的具体内容");BmobACLacl=newBmobACL();//创建ACL对象acl.setReadAccess(BmobUser.getCurrentUser(this),true);//设置当前用户可写的权限acl.setWriteAccess(BmobUser.getCurrentUser(this),true);//设置当前用户可写的权限blog.setACL(acl);//设置这条数据的ACL信息blog.save(this,newSaveListener(){@OverridepublicvoidonSuccess(){//添加成功}@OverridepublicvoidonFailure(intcode,Stringmsg){//添加失败}});角色管理上面的指定用户访问权限虽然很方便,但是对于有些应用可能会有一定的局限性。比如一家公司的工资系统,员工和公司的出纳们只拥有工资的读权限,而公司的人事和老板才拥有全部的读写权限。要实现这种功能,你也可以通过设置每个用户的ACL权限来实现,如下:

//创建公司某用户的工资对象WageInfowageinfo=newWageInfo();wageinfo.setWage(100000);//这里创建四个用户对象,分别为老板、人事小张、出纳小谢和自己BmobUserboss;BmobUserhr_zhang;BmobUsercashier_xie;BmobUserme;//创建ACL对象BmobACLacl=newBmobACL();//设置四个用户读的权限acl.setReadAccess(boos,true);acl.setReadAccess(hr_zhang,true);acl.setReadAccess(cashier_xie,true);acl.setReadAccess(me,true);//设置老板和人事小张对这个工资的写权限acl.setWriteAccess(boss,true);acl.setWriteAccess(hr_zhang,true);//设置工资对象的ACLwageinfo.setACL(acl);wageinfo.save(this,newSaveListener(){@OverridepublicvoidonSuccess(){//保存成功}@OverridepublicvoidonFailure(intcode,Stringmsg){//保存失败}});但是,一个公司的人事、出纳和员工不仅仅只有一个人,同时还会有离职、调换岗位以及新员工加入等问题存在。如果用上面的代码对公司的每个人进行一一设置的话是不现实的,既麻烦也很难维护。针对这个问题,我们可以利用BmobRole来解决。我们只需要对用户进行分类,每个分类赋予不同的权限。如下代码实现:

下面我们来说一下角色与角色之间的从属关系。用一个例子来说明下:一个互联网企业有移动部门,部门中有不同的小组,如Android开发组和IOS开发组。每个小组只拥有自己小组的代码读写权限,但这两个小组同时拥有核心库代码的读权限。

Bmob允许用户根据地球的经度和纬度坐标进行基于地理位置的信息查询。通过在BmobObject的查询中添加一个BmobGeoPoint的对象查询,你就可以实现轻松查找出离当前用户最接近的信息或地点的功能。

首先需要创建一个BmobGeoPoint对象。例如,创建一个东经116.39727786183357度,北纬39.913768382429105度的BmobGeoPoint对象:

BmobGeoPointpoint=newBmobGeoPoint(116.39727786183357,39.913768382429105);查询地理位置信息现在,你的数据表中有了一定的地理坐标对象的数据,这样可以测试找出最接近某个点的信息了。你可以使用BmobQuery对象的addWhereNear方法来这样做:

BmobQuerybmobQuery=newBmobQuery();bmobQuery.addWhereNear("gpsAdd",newBmobGeoPoint(112.934755,24.52065));bmobQuery.setLimit(10);//获取最接近用户地点的10条数据bmobQuery.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});要限制查询指定距离范围的数据可以使用addWhereWithinKilometers、addWhereWithinMiles或addWhereWithinRadians方法。

要查询一个矩形范围内的信息可以使用addWhereWithinGeoBox来实现:

BmobGeoPointsouthwestOfSF=newBmobGeoPoint(116.10675,39.711669);BmobGeoPointnortheastOfSF=newBmobGeoPoint(116.627623,40.143687);BmobQueryquery=newBmobQuery();query.addWhereWithinGeoBox("gpsAdd",southwestOfSF,northeastOfSF);query.findObjects(this,newFindListener(){@OverridepublicvoidonSuccess(Listobject){//TODOAuto-generatedmethodstubtoast("查询成功:共"+object.size()+"条数据。");}@OverridepublicvoidonError(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("查询失败:"+msg);}});注意事项目前有几个需要注意的地方:

很多时候,单纯的前端代码是不能完成全部事情的,一些重要和复杂的业务逻辑还是希望能够在服务端中执行。比如:对比较大量的比赛数据进行排序,对某个网站进行资料采集和处理,获取用户的IP信息,等等。Bmob不仅提供了云端存储,还开放了云端的业务逻辑代码功能,也就是云端代码。

云端代码的执行有多种方法:

其中,在SDK中调用云端代码的方法如下:

AsyncCustomEndpointsace=newAsyncCustomEndpoints();//第一个参数是上下文对象,第二个参数是云端代码的方法名称,第三个参数是上传到云端代码的参数列表(JSONObjectcloudCodeParams),第四个参数是回调类ace.callEndpoint.callEndpoint(MainActivity.this,cloudCodeName,params,newCloudCodeListener(){@OverridepublicvoidonSuccess(Objectobject){//TODOAuto-generatedmethodstubtoast("云端usertest方法返回:"+object.toString());}@OverridepublicvoidonFailure(intcode,Stringmsg){//TODOAuto-generatedmethodstubtoast("访问云端usertest方法失败:"+msg);}});消息推送消息推送简介推送通知是让用户及时被通知、和你的应用保持联系的一种非常棒的方式,你可以快速而有效地通知到所有的用户,下面这个教程将会教你如何使用Bmob来推送消息。

二、在您的应用程序AndroidManifest.xml文件中添加相应的权限:

三、在您的应用程序AndroidManifest.xml文件中注册BmobPushSDK运行所需的推送服务和消息接收器:

四、在你的应用程序中创建一个消息接收器。

Push消息通过action=cn.bmob.push.action.MESSAGE的Intent把数据发送给客户端your.package.MyPushMessageReceiver,消息格式由应用自己决定,PushService只负责把服务器下发的消息以字符串格式透传给客户端。your.package.MyPushMessageReceiver代码示例如下:

publicclassMyPushMessageReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){//TODOAuto-generatedmethodstubif(intent.getAction().equals(PushConstants.ACTION_MESSAGE)){Log.d("bmob","客户端收到推送内容:"+intent.getStringExtra(PushConstants.EXTRA_PUSH_MESSAGE_STRING));}}}五、启动推送服务

在你的应用程序主Activity中调用如下方法:

六、在web端进行推送设置

七、在web端推送消息

在后台推送消息给Android和iOS两个平台的时候,有一些需要注意的:1、由于Android和iOS的提送机制不同,iOS要经过APNS,Android的推送完全是走Bmob的长连接服务,为兼容这个问题,如果你选择发送格式为“json”格式时,需要添加APNS兼容头部(见下面json的aps部分),推送内容格式如下:

{"aps":{"sound":"cheering.caf","alert":"这个是通知栏上显示的内容","badge":0},"xx":"json的key-value对,你可以根据情况添加更多的,客户端进行解析获取",}其中,sound是iOS接收时的声音,badge是iOS通知栏的累计消息数。

2、如果你选择发送格式为“text”时,推送内容为“推送消息测试。。。。”,Bmob会自动添加aps部分发送给APNS,,相当于自动生成如下的json格式的推送内容:

{"aps":{"alert":"推送消息测试。。。。",}}同时,也会发送给Android端,相当于自动生成如下的json格式的推送内容:

{"alert":"推送消息测试。。。。",}3、如果只是发送给Android端,大家可以自定义json格式的数据。

4、由于iOS的APNS的推送的大小是有限制的,默认最多256bytes,因此,如果你需要跨平台互通的话,需注意推送的内容不要太长。

八、源码下载

Bmob官方为大家准备了消息推送的视频教程,有需要的朋友可以移步浏览视频教程:

每一个Bmob的App被安装在用户的设备上后,如果要使用消息推送功能,BmobSDK会自动生成一个Installation对象。Installation对象包含了推送所需要的所有信息。举例:一个棒球的App,你可以让用户订阅感兴趣的棒球队,然后及时将这个球队的消息推送给用户。您可以使用BmobSDK,通过BmobInstallation对象进行一系列操作,就像你存储和获取其他的普通对象一样,比如BmobObject对象。

BmobInstallation对象有几个系统默认的特殊字段来帮助你进行设备定位等管理:

使用消息推送前,首先需要保存设备信息。

BmobInstallation.getCurrentInstallation(this).save();你还可以通过定义继承自BmobInstallation的JavaBean来为BmobInstallation对象添加更多的属性,用来定制更通用的推送。

publicclassMyBmobInstallationextendsBmobInstallation{privateintscore;publicintgetScore(){returnscore;}publicvoidsetScore(intscore){this.score=score;}}订阅频道和退订订阅频道订阅频道可使用subscribe方法

BmobInstallationinstallation=BmobInstallation.getCurrentInstallation(this);installation.subscribe("Giants");installation.subscribe("Mets");installation.save();退订频道退订频道可使用unsubscribe方法

BmobInstallationinstallation=BmobInstallation.getCurrentInstallation(this);installation.unsubscribe("Giants");installation.save();广播推送消息在客户端实现推送消息的功能,通过BmobPushManager对象来完成,比如给所有设备推送一条消息,如下:

BmobPushManagerbmobPush=newBmobPushManager(this);bmobPush.pushMessageAll("HelloBmob.");组播推送消息发送消息给订阅了Giants频道的用户

BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();Listchannels=newArrayList();channels.add("Giants");query.addWhereEqualTo("channels",channels);bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");同时发送消息给多个频道时,可以将其他频道添加在channels中。

BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereLessThan("updatedAt",newBmobDate(newDate()));bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");根据查询条件做推送BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereEqualTo("score",80);bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");请注意,where条件查询的都是installations表。这里是假设installations表存储了score的Number属性,你可以像查询普通对象一样构造where查询

给Android平台的终端推送

BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereEqualTo("deviceType","android");bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");给IOS平台的终端推送

BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereEqualTo("deviceType","ios");bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");根据地理位置信息做推送BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereWithinRadians("location",newBmobGeoPoint(112.934755,24.52065),1.0);bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");上面的例子假设installation表中有个location属性是GeoPoint类型,我们就可以根据地理信息位置做推送。

发送给Android单个客户端

StringinstallationId="客户端installationId";BmobPushManagerbmobPush=newBmobPushManager(this);BmobQueryquery=BmobInstallation.getQuery();query.addWhereEqualTo("installationId",installationId);bmobPush.setQuery(query);bmobPush.pushMessage("消息内容");发送给iOS单个客户端

短信服务的功能包括:

9001

内容:AppKeyisNull,PleaseinitializeBmobSDK.

含义:AppKey为空,请初始化。

9002

内容:Parsedataerror

含义:解析返回数据出错

9003

内容:uploadfileerror

含义:上传文件出错

9004

内容:uploadfilefailure

含义:文件上传失败

9005

内容:Abatchoperationcannotbemorethan50

含义:批量操作只支持最多50条

9006

内容:objectIdisnull

含义:objectId为空

9007

内容:BmobFileFilesizemustbelessthan10M.

含义:文件大小超过10M

9008

内容:BmobFileFiledoesnotexist.

含义:上传文件不存在

9009

内容:Nocachedata.

含义:没有缓存数据

9010

内容:Thenetworkisnotnormal.(Timeout)

含义:网络超时

9011

内容:BmobUserdoesnotsupportbatchoperations.

含义:BmobUser类不支持批量操作

9012

内容:contextisnull.

含义:上下文为空

9013

内容:BmobObjectObjectnames(databasetablename)formatisnotcorrect.

含义:BmobObject(数据表名称)格式不正确

9014

9015

含义:其他错误均返回此code

9016

内容:Thenetworkisnotavailable,pleasecheckyournetwork!

含义:无网络连接,请检查您的手机网络。

由于BmobAndroidSDK本身进行了代码混淆,因此,你在给应用打包编译混淆时,请不要混淆BmobSDK的代码,另外,任何继承自BmobObject、BmobUser的JavaBean请不要混淆。具体可参考BmobExample中proguard-project.txt的代码:

THE END
1.连笔签名设计在线生成采用火焰燃烧的纸张设计出独具风格的艺术签名! 顶尖手写连笔签名设计免费版在线生成,请直接输入您的姓名,在线生成连笔签名拥有630像素*420像素的高清晰度,可以下载到自己电脑上多加练习临摹。 特别提醒:源自急切网的一笔签和连笔签字库齐全,已经完善姓名中的偏僻汉字,请放心设计。http://www.yishuzi.com/_yishuzi/b/m26.htm
2.艺术签名在线生成器最高支持四个字的中文名字设计,如果是英文名请进入英文签名设计专用页面,这里只能输入中文,英文显示乱码。 艺术签名在线生成软件经过多年的迭代,现在是7.0版本,更新了多处细节,如调整签名字与字的间距,优化生成签名的风格等大幅提升用户体验。http://www.kachayv.cn/
3.一笔签名设计在线生成一笔签名设计免费版在线生成-顶尖手写艺术签名设计图 潇洒实用的顶尖手写艺术签名设计,完全免费,在线生成,让您受益终生! 在线生成后一笔签名拥有的清晰度很高:780*520像素,请直接输入您的姓名,接着免费在线设计即可。 特别提醒:一笔签和连笔签字库齐全,已经更新了姓名中的偏僻汉字,请放心设计。http://75.84c.cn/a/m15.htm
4.签名档专用姓名签名设计460*212签名档专用姓名签名设计免费版在线生成! 顶尖手写签名设计,为签名档而生,在线输入您的姓名,把姓名设计成460*212签名档。 设计器原理是用艺术字体转换名字为签名档,同时融入时尚而又个性的元素。内含雨伞、风筝、红心、杯子、草莓、女孩、卡通、黑白、人物等签名素材!特别添加姓名宣言,让您的姓名签名设计更完美http://jiqie.zhenbi.com/a/m17.htm?1627895418
5.手写签名设计手写签名在线生成器签名预览/点图片快速生成 龚帆手写体 李国夫董事长手写体 漫语手写体 奶布儿细手写 品如手写体 青叶手写体 在线设计说明: 在线手写签名设计生成器是利用手写字体在线完成签名设计的快捷设计,六种不同的手写字体在线自动生成你的名字,希望你喜欢。http://www.uustv.com/sx/
6.艺术签名设计免费版艺术签名在线生成草书签名/点图片快速生成 艺术签名设计免费版提供整整四十五款的艺术签名风格供您在线生成,每一款都是精品,让您可以随心所欲的进行在线签名设计。适合签名使用的各种场合,适合每一个年龄层次,从大人到小孩子,从商务合同上的签字需求到校园作业本上的名字写作都能完全满足您的设计要求,楷书、行书等非常适合正式签字场合http://www.akuziti.com/cs/lbqm.php
7.设计师签名免费签名设计生成器在线签名生成转换设计师签名网是中国领先的艺术签名制作平台,免费签名生成转换器支持硬笔签、时尚签、立体签、行楷签等效果,集成草体签、瘦金签、板书签、童体签等功能智能实现在线签名设计,可生成png,svg,pdf格式,请牢记设计师签名 www.ssjjss.comhttp://www.ssjjss.com/
8.androidstudio工程另存为androidstudio怎么保存工程# 自动导包 四、Gradle配置详解 # 全局文件 build.gradle # app 中的 build.gradle 文件 五、快捷输入 # logt 自动生成 TAG 常量 # logd 生成 Log.d 六、修改项目包名【可行】 七、签名 —— 保证开发者合法; 一、下载 - https://www.androiddevtools.cn/# https://blog.51cto.com/u_12204/8260334
9.在线自动生成个性化签名工具,一键快速创建独特签名,支持多种样式在线自动生成个性化签名工具支持多种格式输出包含图片、PDF等。使用者可依据本人的需求选择合适的格式,方便在不同场合采用。 4. 一键分享功能 生成签名后,使用者可点击微信分享按,将签名分享给朋友,展示自身的个性化签名。 三、利用方法 1. 输入名字 在在线自动生成个性化签名工具的界面中,输入您的名字,最多支持三个http://www.guanxian.org/consult/aixuexi/66736.html
10.输入自己名字生成签名输入自己的名字生成签名可以通过以下几种方法:1. 使用logo设计软件:例如xunjiepdf.com/logoshejiapp,在这个软件中找到并点击底部的“工具”选项,接着在跳转页面选择“常用工具”下的“艺术签名”,支持批量生成操作。输入姓名后选择字体、颜色即可立即生成。2. 使用一键logo设计器:例如xunjieshipin.com/yjlogo,在首页找到https://page.sm.cn/blm/midpage-317/index?h=v7.wenda_llm.quark.cn&id=24_88e830b313ebd58a489915e74d8c508e&from=kkframenew
11.C#实现电子签名c#电子签名点击自动适配-,再点击生成: 放大看 点击保存即可,生成透明电子签名图片。 3.在单色背景下手写名字,导入图片生成 先点击 选择图像 按钮,然后选择图像,点击自动适配,点击Canny算法生成,最后点击生成,如下: 双击右边第一张放大: 选择需要的区域点击保存即可。 https://blog.csdn.net/ftfmatlab/article/details/132702818
12.一笔签名设计在线生成一笔签名设计免费版在线生成-顶尖手写艺术签名设计图 潇洒实用的顶尖手写艺术签名设计,完全免费,在线生成,让您受益终生! 在线生成后一笔签名拥有的清晰度很高:780*520像素,请直接输入您的姓名,接着免费在线设计即可。 特别提醒:一笔签和连笔签字库齐全,已经更新了姓名中的偏僻汉字,请放心设计。http://www.jiqie.com/a/m15.htm
13.输入真实名字自动生成网名(周易起名网唯一官网免费)大家好!今天让创意岭的小编来大家介绍下关于输入真实名字自动生成网名的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。 开始之前先推荐一个非常厉害的Ai人工智能工具:开始之前先推荐一个非常厉害的Ai人工智能工具,一键生成原创文章、方案、文案、工作计划、工作报告、论文、代码、作文、做题和对话答疑等等 https://www.de1919.com/article/343203.html
14.输入名字自动生成签名图片!原来名字也有新花样00:00/00:00 输入名字自动生成签名图片!原来名字也有新花样 万泽勇发布于:安徽省2024.03.15 11:53 +1 首赞 输入名字自动生成签名图片!原来名字也有新花样#签名图片https://www.sohu.com/a/764310383_121646611
15.操作指南例如日报表,当我们希望生成一张日报表时,首先需要向报表传递日期参数,然后报表才会根据我们传递进去的如上图所示,在SQL语法里,需要用到参数的地方写上问号,不用考虑参数的数据类型,程序中会自动转换。然后普通参数直接将输入的参数值传给报表进行运算。如果输入的参数值不做任何变化直接传给报表进行计算,我们http://doc.raqsoft.com.cn/report/userrefer/bb34.html
16.N73最全面最强最实用的使用技巧全攻略可以阻挡一些开机会自动运行的程式[或执行档.exe] 也有增加运行内存的效果 2.)在编辑简讯或文字时.按一下可以切换输入法 3.)在编辑简讯或文字时 按住它再按方向键.文字会反白 可以使用复制及贴上的功能 常打简讯的朋友快试试吧 4.)可以标记联络人.文件.简讯等. https://supplier.alibaba.com/article/CTGQ9BNUJ58.htm
17.wm2将系统自带的program files任意改一个名字后再重启机器,再删掉这个任意名字的文件夹,就OK了。不过在删掉系统的program files文件夹前记得先把里面的connetion 和windows media player文件夹拷出来然后在复制到新的program files(storage)文件夹下。建议在操作前最好是先硬启一次机器,把系统的program files里面的文件全部https://www.douban.com/note/176448624/
18.最详细的“云解纷”操作图解来啦!澎湃号·政务澎湃新闻利用“云解纷”平台办案,可以实现全程同步录音录像、实时自动生成笔录并电子签名确认等流程,既满足了当事人足不出户就可以化解纠纷的需求,更能确保诉讼程序合法完善,最大程度地实现了司法便民和司法效能。 用户操作手册—PC 一、用户登录 1.打开谷歌浏览器,输入网址“https://yunjf.gov.cn”打开网页 https://www.thepaper.cn/newsDetail_forward_5564806
19.名字设计签名字体字体转换器2,转换超大字体(超过120px)时,受显示空间限制,您需要将图片在新窗口单独打开才可以看到具体效果!如输入的字体缺少显示,则说明该字体文件不支持该类型字符! 3,字体转换器在线输出图片仅供个人学习参考使用,不得用于商业及非法用途! 下载名字设计签名字体字体https://www.mianfeiziti.com/font_preview-1855.htm
20.PDM技术(精雅篇)通过流程概念模型, 可以自上而下将企业的业务流程一一分解, 这种形式和工作分解的结构存在一种明确的对应关系, 这样一来项目计划的模板就可以根据流程概念图加以生成。随后, 以此为基础进而制定该企业的项目进度计划。通过系统的创建新项目功能, 就可以将工作分解的结构自动生成。在此模式下, 就可以利用流程图或者表格https://www.360wenmi.com/f/cnkey79c6tt6.html
21.6120c常见问题解答设置过密码,为何格机后要我输入存储卡密码?此现象有可能是你设了远程锁定密码,格机后手机系统就自动为存储卡设了同样的密码,用此密码解锁即可,另可能是装了安全类的软件如智能卫士等,并设置过密码,同样用设置的密码解锁试试看。19.PC套件模式连接不到电脑,怎么办?一般这种情况是因为驱动问题造成的,1.鼠标右键单击https://m.360docs.net/doc/1812086453.html
22.在线签名生成器免费,rpa,机器人,自动化艺术签名设计免费版在线生成艺术签名在线生成器2024年9月9日?·?艺术签名在线生成器使用非常方便,只需输入你的名字并选择款式就可以一键生成了,完全免费,不限制次数,你可以完全自由发挥. 最高支持四个字的中文名字设计,如果是 更多内容请查看http://www.kachayv.cn/https://www.wdlinux.cn/html/email/20241211/23845.html
23.真正免费的签名设计软件v1.0绿色特别版(输入名字即自动转换)☉ 如果遇到什么问题,请评论留言,我们定会解决问题,谢谢大家支持! ☉ 本站提供的一些商业软件是供学习研究之用,如用于商业用途,请购买正版。 ☉ 本站提供的真正免费的签名设计软件 v1.0 绿色特别版(输入名字即自动转换)资源来源互联网,版权归该下载资源的合法拥有者所有。https://www.jb51.net/softs/72071.html
24.真正免费的签名设计软件1·0绿色破解版输入名字即自动转换码农真正免费的签名设计软件1·0绿色破解版输入名字即自动转换点赞(0) 踩踩(0) 反馈 所需:1 积分 电信网络下载 suoxin1125 2012-08-31 13:07:44 评论 软件不错,但是字库太少,很多字都显示不出来。。Windows系统安装VMware虚拟机的教程 2024-12-09 04:31:49 积分:1 Windows系统安装VMware虚拟机的教程https://www.coder100.com/index/index/content/id/457074
25.Cp名称生成器下载Cp名称生成器网址入口滑动图片可查看更多>> 游戏简介 Cp名称生成器是一款操作十分简单的取名软件,支持的是cp的取名模式,玩家们任意输入两个的人的名字,系统则会自动生成关于词汇和成语的cp名称,魔性搞笑,感兴趣的小伙伴一起来试试吧。 Cp名称生成器优势 1.基本上不需要你花任何时间。它可以在几秒钟内生成您喜欢的cp名称,超快。 2https://app.ali213.net/android/368605.html
26.手机怎么制作电子签名怎么生成电子版签名接亲网4、截取名字页面 对名字界面进行截图,将截图裁剪至合适大小即可制作成电子签名。 二、怎么生成电子版签名 1、在纸上写下需要的电子签名,并将签名使用相机或者扫描仪制成图片。 2、打开PDF阅读器创建新的PDF文档:主页-空白,创建好空白PDF之后执行:主页-PDF签名。 https://www.jieqinwang.com/baike/121314.html
27.为什么我的图片不能正常显示?比如,如果您添加了邮箱的超链接 kenweinicom@163.com ,当您点击这个邮箱链接时,会自动打开电子邮件客户端,甚至还会自动输入某些内容。温馨提示2:链接地址应该使用绝对地址,即应该包含主域名和目录地址,比如:http://www.kenweini.com/qr,如果写成了www.kenweini.com/qr,则会出错,提示找不到文件。http://diy.kenweini.com/problems
28.Redmine使用介绍–Redmine中文–增强版1. 根据为问题设定的开始日期和完成日期自动生成甘特图和日历 五、 时间跟踪功能 1. 在项目级别或者问题级别设定时间 2. 根据用户, 问题类型, 类别或者活动生成工作量报表 六、 自定义属性 1. 可以为问题, 项目和用户添加自定义属性 2. 可以使用多种格式: 文本, 日期, 证书, 下拉列表, 复选框 http://www.redmine.org.cn/346.html
29.九大名字设计网站签名设计网站排名艺术签名设计网哪个好用如果你不懂这些规则,MAIgoo编辑建议再试用下这款拥有13种艺术签名风格的免费名字设计网站,你可以直接输入你的名字,然后选择喜欢的款式,就可以直接生成签名了。字体如何编排,由网站免费设计,立马可得。 9、真笔网v.zhenbi.com/e/5.htm 艺术签名设计,免费提供连笔签、一笔签、商务签、公务签等多款艺术签名设计。http://www.zhuoyunkang.com/news/show-34658.html