Back

titanium module: shareSDK 的第三方登陆

发布时间: 2015-04-06 08:00:00

shareSDK 是不错的第三方组件. 可以用它来做分享,登陆. 

refer to:  http://wiki.mob.com/%E7%AC%AC%E4%B8%89%E6%96%B9%E7%99%BB%E5%BD%95/

帮助在:http://dashboard.mob.com/ShareSDK/#/quickstarts/android

因为每个系统都会有自己的用户体系(数据库的用户表),  所以我们仅仅让用户与自己的happystock账号做关联.

1. 注册 mob.com

2. 下载对应的 shareSDK.tar.gz 文件,解压缩后, 得到了对应的文件. 

对于titanium module的开发,最核心的两点是:

1. 会写,会看懂基本的 java/ oc代码,知道如何获取activiry , context等

2. 知道如何配置好第三方包的路径(在java下,直接copy jar文件到 lib/ 目录下)

然后,官方给出的使用步骤是:

要数据,不要功能
如果你的应用拥有用户系统,就是说你的应用自己就有注册和登录功能,使用第三方登录只是为了拥有更多用户,那么你可以依照下面的步骤来做:
1、用户触发第三方登录事件
2、showUser(null)请求授权用户的资料(这个过程中可能涉及授权操作)
3、如果onComplete()方法被回调,将其参数Hashmap代入你应用的Login流程
4、否则提示错误,调用removeAccount()方法,删除可能的授权缓存数据
5、Login时客户端发送用户资料中的用户ID给服务端
6、服务端判定用户是已注册用户,则引导用户进入系统,否则返回特定错误码
7、客户端收到“未注册用户”错误码以后,代入用户资料到你应用的Register流程
8、Register时在用户资料中挑选你应用的注册所需字段,并提交服务端注册
9、服务端完成用户注册,成功则反馈客户端引导用户进入系统
10、否则提示错误,调用removeAccount()方法,删除可能的授权缓存数据

看起来比较复杂, 待我仔细敲边代码: 

1. create ti module :      test_ti_module_qq_login 

2. copy 需要的jar 到 android/lib 目录

3. 确认 android/build.properties 文件 是正确的. (记得提交到 git 之后,把它变成 .example 文件后缀) 
否则你可能会收到这个提示: 

Neither the ANDROID_NDK environment variable, or the android.ndk property is not set to an existing Android NDK installation (check your module's build.properties)

# 如果你明明安装了NDK, $ ant 的时候还会收到错误提示说找不到ndk, 就加上 android.ndk  这一行
titanium.platform=/home/sg552/.titanium/mobilesdk/linux/3.5.1.GA/android
android.platform=/workspace/coding_tools/android-sdk-linux/platforms/android-14
google.apis=/workspace/coding_tools/android-sdk-linux/add-ons/addon-google_apis-google-14
android.ndk=/workspace/coding_tools/android-ndk-r10d

4. 上来先什么代码都不要写, 直接 $ cd android,  $ ant 

如果出现提示找不到 gperf,  就安装之: $ sudo apt-get install gperf

如果 出现提示说 生成不了文档, :

BUILD FAILED
/home/sg552/.titanium/mobilesdk/linux/3.5.1.GA/module/android/build.xml:461: /workspace/test_ti_temp/android/build/docs does not exist.
我们就修改 home 目录下的对应的build.xml 文件 , 让它不生成doc:

BUILD FAILED
/home/sg552/.titanium/mobilesdk/linux/3.5.1.GA/module/android/build.xml:461: /workspace/test_ti_temp/android/build/docs does not exist.

461 <zip destfile="${dist}/${module.id}-android-${manifest.version}.zip">
462 <zipfileset file="${module.jar}" prefix="${zip.prefix}"/>
463 <zipfileset file="manifest" prefix="${zip.prefix}"/>
464 <zipfileset file="timodule.xml" prefix="${zip.prefix}"/>
465 <!--
466 <zipfileset dir="${docs}" prefix="${zip.prefix}/documentation"/>
467 -->

4. 修改: android/src/ 目录下的 两个文件之一:   TestTiModuleQqLogin   (另一个叫: ExampleProxy )

  
  public static void onAppCreate(TiApplication app)
  {
    Log.d(LCAT, "inside onAppCreate");
    // 增加这一行
    ShareSDK.initSDK(app);   
    // 下面两行暂时用不到. 
    SHAREICON = getApplicationResource(SHAREICONNAME);
    SHAREICONPATH = copyFileIntoSDCard(app, SHAREICONNAME+".jpg");
  }

5. $ ant , 会得到一个 .zip 文件

开始测试 module: 

1. 新建一个 titanium  project

2. 把上面得到的 my_module.zip 文件, 复制到当前的项目的根目录下。

3. 修改 tiapp.xml

<modules>
  <module platform="android">com.apk</module>
</modules>

4. 在 app/alloy.js 中引用:

var my_module = require('com.apk');
console.info('module: ' + my_module);

5. 然后,我们就可以在 controller js 代码中调用它们了。 

记得两个要点: context 就是 TiApplication的一个实例,  activity 可以通过 context.getCurrentActivity() 来获取。 例如:

  // src/com/happysoft/login/SomeName.java

  @Kroll.onAppCreate
  public static void onAppCreate(TiApplication app)
  {
    android_context = app ; 
    android_current_activity = android_context.getCurrentActivity(); 
    // 其他操作
    ShareSDK.initSDK(app)
  }

如果这个module 用不到 android view, 那么就直接在js代码中调用。 

如果这个module 需要用到自己的VIEW, 接下来就是在controller中调用这个proxy 

proxy 是在生成module的时候, 总共生成的两个java 文件的一个。

对于下面的两个 方法 (getter / setter ) ,  

  @Kroll.getProperty @Kroll.method
  public String getMessage()   
  {
        return "Hello World from my module";
  }

  @Kroll.setProperty @Kroll.method
  public void setMessage(String message) 
  {
      Log.d(LCAT, "Tried setting module message to: " + message);
  }

  // 可以在js 中, 直接 
  proxy = my_module.createExample()
  proxy.message = 'lala'
  a =  proxy.message   
  // a is : 'lala'

my_module.createExample() 这个方法哪里来?

从 ExampleProxy.java 这个名字派生出来。 也就是说,如果你的Proxy名叫:   AnotherStuffProxy.java, 那么就可以:

my_module.createAnotherStuff() 

增加对应的appkey, appid, share_sdk_id

1. android/timodule.xml 增加内容:

<?xml version="1.0" encoding="UTF-8"?>
<ti:module xmlns:ti="http://ti.appcelerator.org" xmlns:android="http://schemas.android.com/apk/res/android">
<!--
Similar to tiapp.xml, but contains module/platform specific
configuration in <iphone>, <android>, and <mobileweb> sections
-->
<iphone>
</iphone>
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<application>
<activity
android:name="cn.sharesdk.framework.ShareSDKUIShell"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustResize" >
<intent-filter>
<data android:scheme="tencent100371282" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> <activity
android:name=".wxapi.WXEntryActivity"
android:exported="true"
android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />

</application>
</manifest>
</android>
<mobileweb>
</mobileweb>
</ti:module>

2. android/assets/ShareSDK.xml 增加内容:

3. 运行代码。  之后就会出现微信登录的页面。

注意:初次开发不建议使用 微信登录, 最好用微博,QQ登录

因为微信对 签名要求的很严格, 必须appid, appkey, sign 一应俱全才行。 出了错误还没提示。。。

4. 登录后,就拉到了, 发现什么事儿也没发生。为什么呢? 因为我们还需要获取用户信息(参考: http://wiki.mob.com/%E8%8E%B7%E5%8F%96%E6%8E%88%E6%9D%83%E7%94%A8%E6%88%B7%E8%B5%84%E6%96%99-2/ )

具体的代码,见:src/cn/sharesdk/tpl/SignupPage.java

  private void initData(){
    String gender = ""; 
    if(platform != null){
      gender = platform.getDb().getUserGender();
      if(gender.equals("m")){
        userInfo.setUserGender(UserInfo.Gender.BOY);
        gender = getContext().getString(R.string.tpl_boy);
      }else{
        userInfo.setUserGender(UserInfo.Gender.GIRL);
        gender = getContext().getString(R.string.tpl_girl);
      }   
          
      userInfo.setUserIcon(platform.getDb().getUserIcon());
      userInfo.setUserName(platform.getDb().getUserName());
      userInfo.setUserNote(platform.getDb().getUserId());
    }   

如果出现 platform.getDb() 得到的数据都是空的话({}) , 就看下 platform.isValid() 的值, 如果是false. 说明授权未通过。

为什么是空呢?  

初步判定是没有使用 微信 提供的 package, 以及没有通过打包。 

下面的代码是登录成功后,java会调用的:

  public void onComplete(Platform platform, int action, HashMap res) {
    System.out.println("==== in onComplete" + res);
  }

所以,当我们点击QQ 空间登录,然后输入完用户名和密码之后,结果如下(知道接下来该如何做了吧):

I/System.out( 4507): ==== in onComplete
{ret=0,
 is_yellow_year_vip=0,
 figureurl_qq_1=http://q.qlogo.cn/qqapp/100371282/B5BB36F4766F3DC1F48E89231F232E5B/40,
 nickname=思维, 
 figureurl_qq_2=http://q.qlogo.cn/qqapp/100371282/B5BB36F4766F3DC1F48E89231F232E5B/100,
 yellow_vip_level=0,
 is_lost=0,
 msg=,
 city=朝阳, 
 figureurl_1=http://qzapp.qlogo.cn/qzapp/100371282/B5BB36F4766F3DC1F48E89231F232E5B/50,
 vip=0,
 figureurl_2=http://qzapp.qlogo.cn/qzapp/100371282/B5BB36F4766F3DC1F48E89231F232E5B/100,
 level=0,
 province=北京, 
 gender=男,
 is_yellow_vip=0,
 figureurl=http://qzapp.qlogo.cn/qzapp/100371282/B5BB36F4766F3DC1F48E89231F232E5B/30}

Back