Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送

Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送


很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送,写这个系列真的很要命,你要去把他们的API文档大致的翻阅一遍,而且各种功能都实现一遍,解决各种bug各种坑,不得不说,极光推送真坑,大家使用还是要慎重,我们看一下极光推送的官网

推送比较使用,很多软件有需要,所以在这个点拿出来多讲讲,我们本节课奇会讲到

  • AndroidPn推送
  • JPush推送
  • JPush实现聊天

一.推送的原理

既然要使用推送,首先我们还是要来了解一下原理,因为我们不仅要使用JPush来实现推送,我们还得自己来实现一个推送,有因必有果,哦弥陀佛!!

推送的方式有两种,大家使用Git的时候也耳熟能详

  • push

    服务端有消息的时候主动向客户端推送消息

  • pull

    客户端向服务器拉取消息,没有消息的话不做操作

但是我们一般也不会去用pull方式,看JPush这个名字就知道,用的是push,因为pull去拉的话,就像ViewGroup要遍历一遍所有的View一样,麻烦,所有又费流又费电量,push推送是服务端要发什么消息就直接发过来了,所有要方便些许

而推送的方式也有很多种,我这里列举几种

  • C2DM云端推送

    Google官方的一个轻量级服务,依赖官方的C2DM服务器,优势在于可以直接和服务器进行通讯,但是我们基本上是无视他的,为什么?我大天朝

  • MQTT协议

    这个我们也可以忽略,因为这个可以说技术积累不够吧,很不稳定,虽然很小,但是要是一个推送都不稳定,那就成了鸡肋的东西了

  • RSMB实现推送

    这个协议有想了解的可以看下这位前辈的Blog:http://blog.csdn.net/jjmm2009/article/details/19496849

    我们这里用一张图来简单说明下

    这个协议我们不做太多的概括

  • XMPP协议

    XMPP协议可谓鼎鼎大名,基本XML的协议,是一个开源的协议,采用的通信模式是C/S(客户端/服务端),而且操作起来相对来说比较简单,同样的,因为基于XML实现,所以数据传输格式也是XML,分布式的特点,这个协议我们就药来多唠叨几句了

    他的工作原理

    客户端连接服务端——服务端进行认证——客户端请求操作——交互

我们等下讲会说一个AndroidPn的推送就是基于XMPP协议的

  • 第三方(JPush,BaiDu之类)

    现在各大平台都有自己的推动服务了,百度,小米,极光,等等等等….


二.AndroidPn实现推送

AndroidPn大家可能用的还是相对要少一点吧

我们简单的来聊聊这个框架

  • 他是基于XMPP协议
  • 包含完整的服务端和客户端
  • 基于openfire开源工程

那我们来实现以下,其实实现起来还是稍微有点复杂的,我们要进行以下的几个步骤

  • 安装TomCat本地服务器(模拟服务器)
  • 下载AndroidPn源码部署在TomCat上
  • 实现推送后台
  • 集成AndroidPn客户端代码
  • 通过浏览器完成推送

我们慢工出细活,一步步来实现

1.安装TomCat服务器

这里我们就不重复讲了,有需要的看这篇十分简单的实现TomCat服务器的搭建

我们开启服务器

我们只要在浏览器能看到

就说明配置完成了

2.下载AndroidPn源码部署在TomCat上

官网地址上面说了

我们直接进去可以看到

我们直接点击Download就可以下载了,他下面有一段描述

An open source project to provide push notification support for Android -- a xmpp based notification server and a client tool kit.

意思就是说:一个开源项目提供推送式通知支持Android——基于xmpp的通知服务器和客户端工具;

我们下载好之后就直接解压

我们可以直接进入bin文件里面启动服务器

到这里,我们的服务器是启动好了,我们可以直接在浏览器里面输入

哈哈,到这里,我们基本的环境就已经部署了,这里我说明一下,AndroidPn的代码下载之后解压随便解压在什么地方,以为之前已经启动了TomCat的原因,所以他会直接依赖

3.实现AndroidPn Client代码

客户端的实现,其实还是分了若干个步骤的,我们一点点来书写,首先我们需要下载一个asmack.jar,用于XMPP传输协议的实现

这里这么多,我就随便下载了一个最新的

好了,我们直接新建一个项目——AndroidPn

然后开始部署了,首先肯定是把jar包放在libs目录下,接着,我们添加网络权限

<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>

最后需要配置我们的秘钥了,在res目录下新建一个raw文件夹,在文件夹下新建一个android.properties文件,添加

apiKey=1234567890
xmppHost=192.168.1.100(你的本地IP)
xmppPort=5222

这些都做完了的话,我们可以直接去清单文件里面注册服务,我们的服务从哪里来?看这里

这是前辈写好的类,我们可以直接拿来用,我会提供这个Demo给大家下载的,好了,我们可以去注册了

 <!--推送服务-->
        <service
            android:name=".client.NotificationService"
            android:enabled="true"
            android:label="NotificationService">
            <intent-filter>
                <action android:name="com.lgl.androidpn.client.NotificationService" />
            </intent-filter>
    </service>

我们回到MainActivity里面

package com.lgl.androidpn;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.lgl.androidpn.client.ServiceManager;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ServiceManager serviceManager = new ServiceManager(this);
        //设置通知栏图标
        serviceManager.setNotificationIcon(R.mipmap.ic_launcher);
        //启动服务
        serviceManager.startService();
    }
}

只要我们启动程序,这个服务就启动了,在此之前,我们还得家点权限

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

现在我们可以运行一下程序,毫无疑问,我们现在的程序是空的,但是在后台可以看到活动

这个时候我们就可以去实现推送了

然后我们接收到了

这里也说明一下,这个AndroidPn小案例也只是告诉大家这个推送的实现原理,以及我们亲手去实现了一遍推送之后得到的宝贵经验,并不推荐使用这个,API过时了,有点蛋疼,而且2010年就已经停止更新了,不推荐使用,我们只要了解原理就可以了


三.JPush实现推送

终于到我们的主角了Jpush极光推送,说实话这个也有点坑

我们根据官网的API文档来讲解

1.集成JPush推送环境

JPush我就不再多做什么介绍了,我简单说一下他的有点(来自网络)

  • SDK采用自定义的协议保持长连接,电量,流量都相对要少
  • 服务器的架构比较先进
  • 高并发可扩展性的云服务

最后加一句,还是有点坑,哈哈,不过正常使用绝对是没有问题的

第三方SDK现在基本上已经不用一步步来了,我们直接新建一个工程——LGLJPush

我们在后台新建一个应用

我们可以根据他的文档来

首先下载SDK

然后添加权限

 <!-- Required 一些系统要求的权限,如访问网络等-->
     <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" />
     <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 

     <!-- Optional for location -->
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

再增加一个自定义的权限

<permission
        android:name="${applicationId}.permission.JPUSH_MESSAGE"
        android:protectionLevel="signature" />

接着我们在application中进行各种注册了

 <!-- Required SDK核心功能-->
         <activity
             android:name="cn.jpush.android.ui.PushActivity"
             android:configChanges="orientation|keyboardHidden"
             android:theme="@android:style/Theme.NoTitleBar"
             android:exported="false">
             <intent-filter>
                 <action android:name="cn.jpush.android.ui.PushActivity" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="${applicationId}" />
             </intent-filter>
         </activity>

         <!-- Required SDK核心功能-->
         <service
             android:name="cn.jpush.android.service.DownloadService"
             android:enabled="true"
             android:exported="false" >
         </service>

         <!-- Required SDK 核心功能-->
         <!-- option since 2.0.5 可配置PushService,DaemonService,PushReceiver,AlarmReceiver的android:process参数 将JPush相关组件设置为一个独立进程 -->
         <!-- 如:android:process=":remote" -->
         <service
             android:name="cn.jpush.android.service.PushService"
             android:enabled="true"
             android:exported="false">
             <intent-filter>
                 <action android:name="cn.jpush.android.intent.REGISTER" />
                 <action android:name="cn.jpush.android.intent.REPORT" />
                 <action android:name="cn.jpush.android.intent.PushService" />
                 <action android:name="cn.jpush.android.intent.PUSH_TIME" />

             </intent-filter>
         </service>

         <!-- Required SDK 核心功能 since 1.8.0 -->
         <service
             android:name="cn.jpush.android.service.DaemonService"
             android:enabled="true"
             android:exported="true">
             <intent-filter >
                 <action android:name="cn.jpush.android.intent.DaemonService" />
                 <category android:name="${applicationId}"/>
             </intent-filter>
         </service>

         <!-- Required SDK核心功能-->
         <receiver
             android:name="cn.jpush.android.service.PushReceiver"
             android:enabled="true"
             android:exported="false">
             <intent-filter android:priority="1000">
                 <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 显示通知栏 -->
                 <category android:name="${applicationId}" />
             </intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.USER_PRESENT" />
                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
             </intent-filter>
             <!-- Optional -->
             <intent-filter>
                 <action android:name="android.intent.action.PACKAGE_ADDED" />
                 <action android:name="android.intent.action.PACKAGE_REMOVED" />
                 <data android:scheme="package" />
             </intent-filter>
         </receiver>

         <!-- Required SDK核心功能-->
         <receiver android:name="cn.jpush.android.service.AlarmReceiver" />

         <!-- User defined. 用户自定义的广播接收器-->
         <receiver
             android:name="您自己定义的Receiver"
             android:enabled="true">
             <intent-filter>
                 <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required 用户注册SDK的intent-->
                 <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required 用户接收SDK消息的intent-->
                 <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required 用户接收SDK通知栏信息的intent-->
                 <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required 用户打开自定义通知栏的intent-->
                 <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!--Optional 用户接受Rich Push Javascript 回调函数的intent-->
                 <action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 -->
                 <category android:name="${applicationId}" />
             </intent-filter>
         </receiver>

         <!-- Required . Enable it you can get statistics data with channel -->
         <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
         <meta-data android:name="JPUSH_APPKEY" android:value="您应用applicationId对应的appKey" /> <!-- </>值来自开发者平台取得的AppKey-->

AS还是比较方便的,这里我们只要修改一下我们自定义的广播和开发者的key就可以,我们新建一个广播——JPushReceiver配置上去就可以了

现在我们可以来初始化了,JPush的初始化需要在Application中进行,所以我们还要新建一个JPushApplication

package com.lgl.lgljpush;

import android.app.Application;

import cn.jpush.android.api.JPushInterface;

/**
 * 初始化JPush
 * Created by LGL on 2016/5/21.
 */
    public class JPushApplication extends Application{

    @Override
    public void onCreate() {
        super.onCreate();
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
    }
}

接着定义一下广播

package com.lgl.lgljpush;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import cn.jpush.android.api.JPushInterface;

/**
 * Jpsuh推送广播
 * Created by LGL on 2016/5/21.
 */
public class JPushReceiver extends BroadcastReceiver {

    public static final String TAG = "JPushReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {

        Bundle bundle = intent.getExtras();
        String action = intent.getAction();

        if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
            String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
            Log.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);

        } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
            Log.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));

        } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
            Log.d(TAG, "[MyReceiver] 接收到推送下来的通知");
            int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
            Log.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);

        } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
            Log.d(TAG, "[MyReceiver] 用户点击打开了通知");
            //打开自定义的Activity

        } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
            Log.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
            //在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等..

        } else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
            boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
            Log.w(TAG, "[MyReceiver]" + intent.getAction() + " connected state change to " + connected);
        } else {
            Log.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
        }
    }
}

这里其实只要定义几个就行,我照着官方的Demo就把所有的广播都写了一遍了。回到我们的控制台

我们点击推送

OK,推送成功了,不过这里要注意的是,我曾一度的被这个问题困扰

可能也怪自己太轻视了吧,于是翻阅了一下资料,根据他的错误找到了问题的所在,其实我们的lib类库是需要加载在Gradle下的,所在,我们可以在build.gradle中的android根节点下配置

  sourceSets.main{
        jniLibs.srcDir ‘libs‘
    }

从而绑定我们的类库,我们看图

OK,我们的极光推送就集成成功了

2.自定义推送

JPush给我们提供了一个比较高级的用法,就是可以在客户端进行推送,需要我们做一些处理,具体是什么呢,我们可以参照一下JPush官方提供的服务端文档

文档中提到,我们需要一个Authorization

通过appKey:masterSecret的组合Base64算法得到的一个数字,这个masterSecret在我们的控制台

在下面的文章中,可能涉及到很多JPush的术语,有些可能我没有阐述到位的地方还是劳烦你多看看上面的文档哦!

推送的必填是平台和设备,JPush 当前支持 Android, iOS, Windows Phone 三个平台的推送。其关键字分别为:”android”, “ios”, “winphone”。

我们举个例子

  • 推送到所有平台:
{ "platform" : "all" }
  • 指定特定推送平台:
{ "platform" : ["android", "ios"] }
  • audience

推送设备对象,表示一条推送可以被推送到哪些设备列表。确认推送设备对象,JPush 提供了多种方式,比如:别名、标签、注册ID、分群、广播等。

  • all

如果要发广播(全部设备),则直接填写 “all”,我们一般也是填all

OK,我们开始第一步,用Base64算法得到我们的秘钥,网上搜索一下Base64的在线解码

开始解码

我们就可以得到秘钥了

  • YzNlNDIyODdiZjQ4Y2NmYWQ4N2MwNDEyOmFkMmNiNDMxZmNmZDAwMWIwNzBjNTlhMSA=

这里我们使用的是HttpClient的Post请求,所以你必须在Gradle的文件里面加入

 useLibrary ‘org.apache.http.legacy‘

看图更加形象一点

我们写个布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="15dp">

    <EditText
        android:id="@+id/et_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入消息" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="发送" />

</LinearLayout>

很简单,就一个输入框和一个按钮,我们要做的事情也很简单,点击发送按钮之后就发送消息,通过开启一个子线程去实现,大概的代码

package com.lgl.lgljpush;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class MainActivity extends AppCompatActivity {

    //发送按钮
    private Button btn_send;
    //文本框
    private EditText et_content;
    //要发送的文本
    private String text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_send = (Button) findViewById(R.id.btn_send);
        et_content = (EditText) findViewById(R.id.et_content);

        btn_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //拿到输入框的内容
                text = et_content.getText().toString();
                //判断不能为null
                if (!TextUtils.isEmpty(text)) {
                    new Thread(runnable).start();
                } else {

                    Toast.makeText(MainActivity.this, "请输入文字", Toast.LENGTH_SHORT).show();
                }

            }
        });
    }

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                //Post初始化
                String url = "https://api.jpush.cn/v3/push";
                HttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);

                //添加头部信息
                httpPost.addHeader("Authorization", "Basic YzNlNDIyODdiZjQ4Y2NmYWQ4N2MwNDEyOjY4Zjg2MTIxMDM2YjNhODRmOWRhN2VhOA==");
                //定义Json请求
                httpPost.addHeader("Content-Type", "application/json");

                //添加字段
                JSONObject obj = new JSONObject();
                obj.put("platform", "all");
                obj.put("audience", "all");
                JSONObject notification = new JSONObject();
                JSONObject android = new JSONObject();
                android.put("alert", text);
                notification.put("android", android);
                obj.put("notification", notification);

                httpPost.setEntity(new StringEntity(obj.toString()));

                HttpResponse response = httpClient.execute(httpPost);

                //打印返回码
                Log.e("返回码", response.getStatusLine().getStatusCode() + "");

            } catch (JSONException e) {
                e.printStackTrace();
                Log.e("返回码", "JSONException");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                Log.e("返回码", "UnsupportedEncodingException");
            } catch (ClientProtocolException e) {
                e.printStackTrace();
                Log.e("返回码", "ClientProtocolException");
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("返回码", "IOException");
            } catch (StackOverflowError e) {
                Log.e("返回码", "StackOverflowError");
            }

        }
    };

    /**
     * 发送消息 Post方式发送
     *
     * @param date
     * @return
     */
    private String sendMessage(String date) {

        return "";
    }

}

我自问我的代码写的还是逻辑很清晰的,相信你一定能看懂,好了,看下运行的返回码

那就说明成功了,我们看一下运行的结果

这里我用的是模拟器,所以不能输入中文,我们可以看到我发送的消息是ddd,然后手机就接收到了,其实,我们可以根据设备进行推送,而且可以指定推送内容,这样,是不是我们可以根据逻辑实现一个聊天的小应用?这里本来想写的。篇幅太多了,留着以后有时间写吧,感兴趣的可以自己去实现以下,根据注册ID去发送消息,JPush也给我们提供了接口

 Log.e("ID", JPushInterface.getRegistrationID(this));
  • Nexus 5x: 140fe1da9eab772de2c

OK,我们这篇就先到这里,感谢你的观看,觉得不错的可以点个赞

我的群:555974449

Demo下载:http://download.csdn.net/detail/qq_26787115/9527044

时间: 2024-10-03 21:53:34

Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送的相关文章

Android项目刮刮奖详解(三)

Android项目刮刮奖详解(二) 前言 上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下 目标 将刮刮奖的宽高改为合适高度 将刮刮奖位置居中 将信息层的图片换成文字(重点) 实现 将刮刮奖的宽高改为合适高度和将刮刮奖位置居中 这里其实很简单,我们直接到layout布局之中将大小修改一下即可,同时,在布局中利用gravity修改位置 <?xml version="1.0" encoding="utf-8"?> <LinearLay

Android OTA升级包制作脚本详解(三,打包)

这是在ota_from_target_files中mian函数中打包的主要流程语句: #抽象一个新的临时文件 temp_zip_file = tempfile.NamedTemporaryFile() #创建一个zip包用来进行打包 output_zip = zipfile.ZipFile(temp_zip_file, "w", compression=zipfile.ZIP_DEFLATED) #判断是差分还是整包 if OPTIONS.incremental_source is N

Android第三方登录详解1

android第三方登录是一种很流行的方式下面我来讲讲怎么做 1.打开百度搜   友盟 2.进入官网 注册 登录进入主页面 3.点击添加新应用 进入 4.提交  会生成一个K值 5.点击最上面的文档中心 进入 6.点击社会下分享  机器人 7.点击sdk下载 8.找到Android社会化组件sdk (看个人情况选择版本)点击下载 9.勾选要的第三方登录下载会下载一个压缩包 解压 10.点击最后一个jar包 11.现在对应android项目 填写对应K值点击快速集成  完了刷新android项目

Android第三方登录详解2

接着Android第三方登录详解1讲 1.找到友盟  文档中心 2.找到 3.将 UMSocialService mController = UMServiceFactory.getUMSocialService("com.umeng.login");       这句话放到对应activity 弄成全局即可 4QQ 登录 //参数1为当前Activity, 参数2为开发者在QQ互联申请的APP ID,参数3为开发者在QQ互联申请的APP kEY. UMQQSsoHandler qqS

Android APK优化工具Zipalign详解

最近在googl play上发布apk要优化 Android SDK中包含一个"zipalign"的工具,它能够对打包的应用程序进行优化.在你的应用程序上运行zipalign,使得在运行时Android与应用程序间的交互更加有效率.因此,这种方式能够让应用程序和整个系统运行得更快.我们强烈推荐在新的和已经发布的程序上使用zipalign工具来得到优化后的版本 一.这里下载android SDK,只为了用他的zipalign工具,当然什么时候大家有兴趣了用来开发两个小程序也是很简单的 A

Android触摸屏事件派发机制详解与源码分析

请看下面三篇博客,思路还是蛮清晰的,不过还是没写自定义控件系列哥们的思路清晰: Android触摸屏事件派发机制详解与源码分析一(View篇) http://blog.csdn.net/yanbober/article/details/45887547 Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇) http://blog.csdn.net/yanbober/article/details/45912661 Android触摸屏事件派发机制详解与源码分析三(Activi

iOS SDK详解之NSCoding协议

原创blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=contents 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSCoding是对iOS中的Model类进行编码和解码必须要遵循的协议,如果一个对象要被归档,那么这个协议是必须的. NSCoding要实现两个方法 - initWithCoder: //解码 - enc

IOS SDK详解

来源:http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html?page=1#42803301 博客专栏>移动开发专栏>IOS SDK详解 分享到:新浪微博腾讯微博IOS SDK详解 本专栏从IOS SDK中常用的Framework出发,继而深入的介绍各个Framework.每个Framework博主都会进行Demo 收藏 订阅 最新更新文章 [移动开发] IOS SDK详解之CALayer(二) 原创Blog,转载请注明出处

[Android新手区] SQLite 操作详解--SQL语法

该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解析大部分标准SQL语言.但它也省去了一些特性并且加入了一些自己的新特性.这篇文档就是试图描述那些SQLite支持/不支持的SQL语法的.查看关键字列表. 如下语法表格中,纯文本用蓝色粗体显示.非终极符号为斜体红色.作为语法一部分的运算符用黑色Roman字体表示. 这篇文档只是对SQLite实现的SQ