android_android studio - CSDN
android 订阅
安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机、智能手表等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%。2013年09月24日谷歌开发的操作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。2014第一季度Android平台已占所有移动广告流量来源的42.8%,首度超越iOS。但运营收入不及iOS。 [1] 展开全文
安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机、智能手表等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%。2013年09月24日谷歌开发的操作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。2014第一季度Android平台已占所有移动广告流量来源的42.8%,首度超越iOS。但运营收入不及iOS。 [1]
信息
更新时间
2019年9月4日 [2]
源码模式
自由及开放源代码软件
发行日期
2008年9月23日
软件许可
Apache License、 GPL等
创始人
安迪·鲁宾(Andy Rubin)
软件语言
C/C++(底层) Java,Kotlin等(应用层)
开发商
Google、开放手持设备联盟
发行商
Google - 谷歌(美国)
软件版本
Android 10(正式版) [2]
软件平台
Google
内核类型
宏内核(Linux内核)
测试版本
Android 11 Developer Preview 3(开发者预览版)
系统家族
类Unix,Linux
软件名称
Android(安卓)
Android系统简介
Android一词的本义指“机器人”,同时也是Google于2007年11月5日 Android logo相关图片(33张) 宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。Android一词最早出现于法国作家利尔亚当(Auguste Villiers de l'Isle-Adam)在1886年发表的科幻小说《未来夏娃》(L'ève future)中。他将外表像人的机器起名为Android。Android的Logo是由Ascender公司设计的,诞生于2010年,其设计灵感源于男女厕所门上的图形符号,于是布洛克绘制了一个简单的机器人,它的躯干就像锡罐的形状,头上还有两根天线,Android小机器人便诞生了。其中的文字使用了Ascender公司专门制作的称之为“Droid ” 的字体。Android是一个全身绿色的机器人,绿色也是Android的标志。颜色采用了PMS 376C和RGB中十六进制的#A4C639来绘制,这是Android操作系统的品牌象徵。有时候,它们还会使用纯文字的Logo。2012年7月美国科技博客网站BusinessInsider评选出二十一世纪十款最重要电子产品,Android操作系统和iPhone等榜上有名。(Android logo 相关图片相册图片来源:)
收起全文
  • 这是一门快速入门Android开发课程,顾名思义是让大家能快速入门Android开发。 学完能让你学会如下知识点: Android的发展历程 搭建Java开发环境 搭建Android开发环境 ...
  • Android编程经典200例

    2020-07-30 23:33:19
    资源名称:Android编程经典200例内容简介:本书通过200个经典实例全面、系统地介绍了Android平台下的软件开发知识,重点突出、涉及面广、实用性强,在实例的讲解过程中还详细分析了开发思路及侧重点,使读者达到...
  • Android Studio 开发详解

    万人学习 2019-12-18 15:09:34
    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。
  • 一、Android简介

    千次阅读 2018-08-14 21:15:22
     从接触Android学习到开发马上就有3年了,讲道理是不是也该算是一个熟练的码农了(啥时候能成大牛啊),但是你问我Android都有哪些技术啊,开发过程中都有什么难点啊,好吧,我还真的不知道从何讲起,所以下定了...

    引言:

            从接触Android学习到开发马上就有3年了,讲道理是不是也该算是一个熟练的码农了(啥时候能成大牛啊),但是你问我Android都有哪些技术啊,开发过程中都有什么难点啊,好吧,我还真的不知道从何讲起,所以下定了决心,准备像各路大牛学习,坚持写博客,整理记录自己的脑子里的知识。都说写博客特别耗费时间,但是时间嘛就像女人的胸,挤挤总是会有的(坏笑)。好,不多多逼逼,下面开始...

    一、Android系统简介

    Android系统:Google公司发布的手机或者平板上的运行系统,现在最新(180814)的系统更新到了9.0吧,世界上4.03之前的系统应该没人再用了,在Android创建新项目的时候,最低版本选择4.03的时候,它就告诉我,这个选项已经含括了世界上100%的终端设备。每次大的升级都有很多新特性,接下来简单记录一下:

    1、Android 5.0

    (1)5.0之前Android系统都是运行在Dalvik虚拟机上,5.0之后运行环境是ART虚拟机,提升了运行速度。

    (2)提出Material Design设计风格来美化界面设计

      (3) .......

    2、Android 6.0

    (1)运行时权限管理

    (2)电量优化

    (3)规范化APP Link

    (4).......

    3、Android 7.0

    (1)新的Notifycations

    (2)多窗体支持(分屏模式)

    (3)随时随地低耗电

    (4)优化大型应用的安装速度

    (5)......

    4、Android 8.0

    (1)TensorFlow Lite 人工智能的尝试

    (2)画中画,在你使用的程序中可以小窗使用其他程序

    (3) Notifycations Dots 应用程序图标上出现通知小点提示,长按可查看

    (4)Play Console Dashboard 开发人员工具(还没用过,准备看看)

    (5)自定义字体终于支持了

    (6)....

    5、Android 9.0

    (1)室内wifi定位

    (2)刘海平的支持(好吧,我一直觉得很丑)

    (3)Notifycation (每个版本你都改)

    (4)通道设置,广播以及免打扰

    (5)多相机支持

    (6)新的图片解码,动画优化

    (7)....

    Android版本基本上是一年一个,哎,感觉做一个Android程序猿好累啊,每天都要学习新东西,不然很容易就被谷歌抛弃了,5.0之前的技术我就不建议大家去看了,感觉5.0以上机型基本都是最低国人配置了。好吧东西很多,写到这里发现自己要学习的东西还很多,接下来再介绍一下Android的系统架构...

    二、Android系统架构

    Android系统分为四层架构

    1、Linux内核层

        Android系统是基于Linux内核的,Android系统提供硬件的驱动,音频驱动,视频驱动,蓝牙,wifi驱动等等吧。(一般作为android应用开发,没必要学习这些东西)

    2、系统运行库层

    C/C++ 为Android提供解决一些Java代码干不好的事,比如OpenGL/ES 3D绘图,WebKit提供了浏览器内核的支持。(这个作为android开发的我们来说还是很值得学习)

    3、应用框架层

    提供Android构建程序所需要的API,我感觉就是SDK

    4、应用层

    安装在你手机上的应用程序就是组成这一层的东西了

    今天就写这么多了,我呢是被我的学长带入的Android之路(坑),当时他就和我说,Android学起来不是很难,就是学习面比较杂,要学的东西很多,现在想起来,真的是。。。放屁,要学的东西那叫超级多好么,而且我怎么没感觉到简单呢。。。

    展开全文
  • Android四大组件之ContentProvider

    千人学习 2019-06-26 11:52:14
    本课程向大家讲述Android中的四大组件之一ContentProvider(内容提供者)
  • Android&融云单聊的实现

    千次阅读 2017-11-14 15:45:45
    1)首先下载融云即时通讯的SDK 导入融云的通讯界面库,以及通讯功能库 IMKit,IMLib 2)在build.gradle中的dependencies中添加 compile project(':IMKit') compile project(':IMLib') ...aut

    QQ群 :  668524118

    这里写的比较简单 ,

    如有不懂的地方 ,欢迎加群询问 .


    1)首先下载融云即时通讯的SDK

    导入融云的通讯界面库,以及通讯功能库

    IMKit,IMLib


    2)build.gradle中的dependencies中添加

    compile project(':IMKit')
    compile project(':IMLib')

    然后syon now,就Ok

     

    mainfest中添加

    authorities中换成   自己的包名. FileProvider

    下边activityname换成自己的,这是在连接融云的服务器(建议写在登录的时候)

    <!-- 融云 -->
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="cm.hetao.yingyue.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/rc_file_path" />
    </provider>
    
    <!-- 登录 -->
    <activity android:name=".activity.LoginActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
    
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <activity android:name=".activity.MainActivity" />
    
    <!-- 会话列表 -->
    <activity
        android:name=".activity.MessageActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
    
            <category android:name="android.intent.category.DEFAULT" />
    
            <data
                android:host="cm.hetao.yingyue"
                android:pathPrefix="/conversationlist"
                android:scheme="rong" />
        </intent-filter>
    </activity>
    
    <!-- 会话界面 -->
    <activity
        android:name=".activity.ChatInterfaceActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
    
            <category android:name="android.intent.category.DEFAULT" />
    
            <data
                android:host="cm.hetao.yingyue"
                android:pathPrefix="/conversation/"
                android:scheme="rong" />
        </intent-filter>
    </activity>
    3)创建融云账号,创建自己的应用,在api调试中 获取Token
    将获取到的token放进去,去连接融云的服务器

    这些可以写在登录界面

    /**
         * 连接融云服务器
         *
         * @param token
         */
        public void connectRongServer(String token) {
            RongIM.connect(token, new RongIMClient.ConnectCallback() {
                @Override
                public void onSuccess(final String userId) {
                    Log.e("error", "成功");
    //                RongIM.getInstance().enableNewComingMessageIcon(true);//显示新消息提醒
                    RongIM.getInstance().enableUnreadMessageIcon(true);//显示未读消息数目
                    RongIM.setUserInfoProvider(new RongIM.UserInfoProvider() {
                        @Override
                        public io.rong.imlib.model.UserInfo getUserInfo(String s) {
                            return findUserInfo(s);
                        }
                    }, true);
                }
    
                @Override
                public void onError(RongIMClient.ErrorCode errorCode) {
                    Log.e("erroy", "connect failure errorCode is :" + errorCode.getValue());
                }
    
                @Override
                public void onTokenIncorrect() {
                    Log.e("erroy", "token is error , please check token and appkey ");
                }
            });
        }
    
        /**
         * 根据user_id去查找用户信息
         *
         * @param user_id 发送消息的用户id
         */
        private io.rong.imlib.model.UserInfo findUserInfo(String user_id) {
            if (user_id.equals("sys")) {
                return new io.rong.imlib.model.UserInfo(user_id, "系统消息", Uri.parse(MyApplication.SERVICE_IMAGE));
            }
            String resVlt = String.format(Constants.CHAT_USER_DETAIL, Integer.valueOf(user_id));
            HttpHelper.getInstance().get(MyApplication.getTokenURL(resVlt), null, new HttpHelper.XCallBack() {
                @Override
                public void onResponse(String result) {
                    try {
                        JSONObject object = new JSONObject(result);
                        JSONObject data = object.getJSONObject("data");
                        friend = new Friend(data.getString("id"), data.getString("name"), data.getString("head_img"));
                    } catch (Exception e) {
                        Log.e("HttpHelper", e.toString());
                    }
                }
            });
            if (friend != null) {
                return new io.rong.imlib.model.UserInfo(friend.getId(), friend.getName(), Uri.parse(MyApplication.IMAGE_HOST + friend.getHead_img()));
            } else {
                return null;
            }
        }
    
        private void getRyService() {
            RongIM.setConnectionStatusListener(new RongIMClient.ConnectionStatusListener() {
                @Override
                public void onChanged(RongIMClient.ConnectionStatusListener.ConnectionStatus status) {
                    if (ConnectionStatus.KICKED_OFFLINE_BY_OTHER_CLIENT == status) {
                        Log.e("error", "被顶号");
                    }
                    Log.e("error", "网络状态已经变化");
                }
            });
    
            // 声明消息监听器,建议在 Application 中声明为成员变量。
            RongIM.setOnReceiveMessageListener(new RongIMClient.OnReceiveMessageListener() {
                @Override
                public boolean onReceived(final Message message, int arg1) {
                    return false;
                }
            });
        }

    因为融云是不会保存用户的信息数据的,所以你需要自己去保存用户的信息数据.

    我是创建了一个实体类来保存的

    /**
     * 融云用户信息
     */
    public class Friend implements Serializable {
    
        private String id;
        private String name;
        private String head_img;
    
        public Friend(String id, String name, String head_img) {
            this.id = id;
            this.name = name;
            this.head_img = head_img;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getHead_img() {
            return head_img;
        }
    
        public void setHead_img(String head_img) {
            this.head_img = head_img;
        }
    }
    

    刷新用户数据

    private void refreshUserInfoCache(UserInfo user) {
        //刷新用户数据
        io.rong.imlib.model.UserInfo userInfo = new io.rong.imlib.model.UserInfo(user.getId() + "", user.getName(), Uri.parse(user.getMember().getHead_img()));
        RongIM.getInstance().refreshUserInfoCache(userInfo);
    }

    融云的推送服务信息配置

    <!-- 融云推送服务 -->
    <receiver-
        android:name=".receive.SealNotificationReceive"
        android:exported="true">
        <intent-filter>
            <action android:name="io.rong.push.intent.MESSAGE_ARRIVED" />
            <action android:name="io.rong.push.intent.MI_MESSAGE_ARRIVED" />
            <action android:name="io.rong.push.intent.MESSAGE_CLICKED" />
            <action android:name="io.rong.push.intent.MI_MESSAGE_CLICKED" />
        </intent-filter>
    </receiver->
    
    <!-- 必选: SDK 核心功能 -->
    <!-- 第三方相关,向第三方推送服务请求 token 的服务 -->
    <service
        android:name="io.rong.push.core.PushRegistrationService"
        android:exported="false" />
    
    <!-- 处理 push 消息相关的服务 -->
    <service
        android:name="io.rong.push.core.MessageHandleService"
        android:exported="true" />
    
    <!-- push服务 -->
    <service
        android:name="io.rong.push.PushService"
        android:exported="true"
        android:process="io.rong.push"> <!-- push进程,可以改名 -->
    </service>
    
    <!-- push 相关事件接收器 -->
    <receiver
        android:name="io.rong.push.PushReceiver"
        android:process="io.rong.push">
    
        <!-- 此处进程可以改名,名称需要和PushService所在进程统一 -->
    
    
        <!-- 心跳事件 -->
        <intent-filter>
            <action android:name="io.rong.push.intent.action.HEART_BEAT" />
        </intent-filter>
        <!-- 网络变动事件 -->
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
        <!-- 部分用户事件 -->
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.USER_PRESENT" />
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

    会话列表页面布局( conversationlist是固定的 )

    <FrameLayout
        android:id="@+id/conversationlist"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    会话列表页面具体实现( 本人用的是xutils3框架 )

    /**
     * 消息
     */
    @ContentView(R.layout.activity_message)
    public class MessageActivity extends BaseActivity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setStyle(STYLE_HOME);
            setCaption("消息");
    
            //设置消息体内是否携带用户信息。
            RongIM.getInstance().setMessageAttachedUserInfo(true);
        }
    
        @Override
        protected void onResume() {
            IsNeedLoginActivity();
            initMesageNumber();
            initPlugin();
    
            ConversationListFragment fragment = new ConversationListFragment();
            Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon()
                    .appendPath("conversationlist")
                    .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false") //设置私聊会话非聚合显示
                    .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "true")//设置群组会话聚合显示
                    .appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")//设置讨论组会话非聚合显示
                    .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")//设置系统会话非聚合显示
                    .build();
            fragment.setUri(uri);
    
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            //rong_content 为你要加载的 id
            transaction.add(R.id.conversationlist, fragment);
            transaction.commit();
            super.onResume();
        }
    
        /**
         * 初始化Plugin图标
         */
        private void initPlugin() {
            List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
            IExtensionModule defaultModule = null;
            if (moduleList != null) {
                for (IExtensionModule module : moduleList) {
                    if (module instanceof DefaultExtensionModule) {
                        defaultModule = module;
                        break;
                    }
                }
                if (defaultModule != null) {
                    RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                    RongExtensionManager.getInstance().registerExtensionModule(new SampleExtensionModule());
                }
            }
        }
    
        private class SampleExtensionModule extends DefaultExtensionModule {
            private EditText mEditText;
    
            @Override
            public List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) {
    //        super.getPluginModules(conversationType);  如果需要对红包进行排序可从父类中的 getPluginModules 集合中过滤取出 JrmfExtensionModule
                List<IPluginModule> pluginModuleList = new ArrayList<>();
    
                pluginModuleList.add(new BaiDuLocationPlugin());
                pluginModuleList.add(new ImagePlugin());
                pluginModuleList.add(new FilePlugin());
                // 此时扩展区域的展示顺序应该为 : 百度地图、图片、文件
                return pluginModuleList;
            }
    
    
            @Override
            public void onAttachedToExtension(RongExtension extension) {
                mEditText = extension.getInputEditText();
            }
    
            @Override
            public void onDetachedFromExtension() {
                mEditText = null;
            }
    
            @Override
            public List<IEmoticonTab> getEmoticonTabs() {
                return super.getEmoticonTabs();
            }
        }
    }

    通过在AndroidManifest文件中的配置来进行隐式调用( name一样是固定的 )

    <fragment
        android:id="@+id/conversation"
        android:name="io.rong.imkit.fragment.ConversationFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    会话界面具体实现逻辑( 我这里添加了因为项目需求添加了一些自定义消息 )

    /**
     * 聊天界面
     */
    @ContentView(R.layout.activity_chat_interface)
    public class ChatInterfaceActivity extends BaseActivity {
        @ViewInject(R.id.conversation)
        private Fragment conversation;
    
        private String targetid = "";   //用户id
        private OrderITextMsgMessage orderITextMsgMessage;  //邀单消息
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        protected void onResume() {
            initPlugin();
            initData();
            super.onResume();
        }
    
        private void initData() {
            switch (SharedPreferencesUtils.getIntPreferences(SharedPreferencesUtils.CONFIG_USER_TYPE)) {
                case 2: //达人
                    String resvlt = String.format(Constants.TALENT_TALENTID_PROFILE, MyApplication.getUserId());
                    HttpHelper.getInstance().get(MyApplication.getTokenURL(resvlt), null, this, new onTalentProflieXCallBack());
                    break;
                case 3: //会员
                    HttpHelper.getInstance().get(MyApplication.getTokenURL(Constants.MEMBER_PROFILE), null, this, new onMemberProflieXCallBack());
                    break;
            }
        }
    
        /**
         * 初始化Plugin图标
         */
        private void initPlugin() {
            List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
            IExtensionModule defaultModule = null;
            if (moduleList != null) {
                for (IExtensionModule module : moduleList) {
                    if (module instanceof DefaultExtensionModule) {
                        defaultModule = module;
                        break;
                    }
                }
                if (defaultModule != null) {
                    RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                    RongExtensionManager.getInstance().registerExtensionModule(new SampleExtensionModule());
                }
            }
        }
    
        /**
         * 初始化会话界面的监听事件
         */
        private void initChatListener() {
            //设置消息体内是否携带用户信息。
            RongIM.getInstance().setMessageAttachedUserInfo(true);
    
            setStyle(STYLE_BACK_QUERY);
            targetid = getIntent().getData().getQueryParameter("targetId");//获取id
            if (String.valueOf(targetid).equals(String.valueOf("sys"))) {
                setCaption(getIntent().getData().getQueryParameter("title"));   //获取消息title
            } else {
                setCaption(getIntent().getData().getQueryParameter("title"));   //获取消息title
            }
            setTitleBarImageResource(R.drawable.yy_head_yaoqing).setOnTitleBarRightImgListener(new onTitleBarRightImgListener() {
                @Override
                public void onTitleBarRightImgListener() {
                    Intent intent = new Intent();
                    try {
                        intent.putExtra("id", Integer.valueOf(targetid));
                        if (MyApplication.getUserId() == Integer.valueOf(targetid)) {
                            return;
                        }
                    } catch (Exception e) {
                        return;
                    }
                    intent.putExtra("is_chat", "chatinterface");
                    openActivity(intent, TalentDetailActivity.class);
                }
            });
    
            /**
             * 消息页面的 消息 头像等监听事件
             */
            RongIM.setConversationBehaviorListener(new RongIM.ConversationBehaviorListener() {
                @Override
                public boolean onUserPortraitClick(Context context, Conversation.ConversationType conversationType, io.rong.imlib.model.UserInfo userInfo) {
                    //消息头像点击事件
                    return false;
                }
    
                @Override
                public boolean onUserPortraitLongClick(Context context, Conversation.ConversationType conversationType, io.rong.imlib.model.UserInfo userInfo) {
                    //消息头像长按事件
                    return false;
                }
    
                @Override
                public boolean onMessageClick(Context context, View view, Message message) {
                    Intent intent = new Intent();
                    //点击消息处理事件,  message.getContent() 获得消息内容
                    if (message.getContent() instanceof LocationMessage) {  //位置消息
                        LocationMessage locationMessage = (LocationMessage) message.getContent();
                        intent.putExtra("lng", locationMessage.getLng());
                        intent.putExtra("lat", locationMessage.getLat());
                        openActivity(intent, BaiDuLocationDetailActivity.class);
                    }
                    if (message.getContent() instanceof ImageMessage) {     //图片消息
                        ImageMessage imageMessage = (ImageMessage) message.getContent();
                        intent = new Intent();
                        intent.putExtra("photo", imageMessage.getLocalUri() == null ? imageMessage.getRemoteUri().toString() : imageMessage.getLocalUri().toString());
                        if (imageMessage.getThumUri() != null) {
                            intent.putExtra("thumbnail", imageMessage.getThumUri());
                        }
                        openActivity(intent, PhotoDetailActivity.class);
                    }
                    if (message.getContent() instanceof UserTextMsgMessage) {    //用户的审核消息
                        UserTextMsgMessage userTextMsgMessage = (UserTextMsgMessage) message.getContent();
                        intent = new Intent();
                    }
                    if (message.getContent() instanceof OrderTextMsgMessage) {    //订单消息
                        OrderTextMsgMessage orderTextMsgMessage = (OrderTextMsgMessage) message.getContent();
                        intent = new Intent();
                        intent.putExtra("status", orderTextMsgMessage.getStatus());
                        intent.putExtra("id", orderTextMsgMessage.getId());
                        openActivity(intent, OrderTextMsgDetailActivity.class);
                    }
                    if (message.getContent() instanceof OrderITextMsgMessage) {    //邀单消息
                        orderITextMsgMessage = (OrderITextMsgMessage) message.getContent();
                        String resvlt = String.format(Constants.ORDER_INVITE_DETAIL, orderITextMsgMessage.getId());
                        HttpHelper.getInstance().get(MyApplication.getTokenURL(resvlt), null, ChatInterfaceActivity.this, new onOrderInviteDetailXCallBack());
                    }
                    return true;
                }
    
                @Override
                public boolean onMessageLinkClick(Context context, String s) {
                    //链接消息点击事件
                    return false;
                }
    
                @Override
                public boolean onMessageLongClick(Context context, View view, Message message) {
                    //消息长按事件
                    return false;
                }
            });
        }
    
        private class SampleExtensionModule extends DefaultExtensionModule {
            private EditText mEditText;
    
            @Override
            public List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) {
    //        super.getPluginModules(conversationType);  如果需要对红包进行排序可从父类中的 getPluginModules 集合中过滤取出 JrmfExtensionModule
                List<IPluginModule> pluginModuleList = new ArrayList<>();
    
                pluginModuleList.add(new BaiDuLocationPlugin());
                pluginModuleList.add(new ImagePlugin());
                pluginModuleList.add(new FilePlugin());
                // 此时扩展区域的展示顺序应该为 : 百度地图、图片、文件
                return pluginModuleList;
            }
    
    
            @Override
            public void onAttachedToExtension(RongExtension extension) {
                mEditText = extension.getInputEditText();
            }
    
            @Override
            public void onDetachedFromExtension() {
                mEditText = null;
            }
    
            @Override
            public List<IEmoticonTab> getEmoticonTabs() {
                return super.getEmoticonTabs();
            }
        }
    
        /**
         * 达人详情
         */
        private class onTalentProflieXCallBack implements HttpHelper.XCallBack {
            @Override
            public void onResponse(String result) {
                TalentDetailInfo talentDetailInfo = null;
                try {
                    talentDetailInfo = getHttpResult(result, TalentDetailInfo.class);
                } catch (Exception e) {
                    showToastText(e.toString());
                }
                if (talentDetailInfo != null) {
                    RongIM.getInstance().refreshUserInfoCache(new io.rong.imlib.model.UserInfo(String.valueOf(talentDetailInfo.getTalent().getId()), talentDetailInfo.getTalent().getName(), Uri.parse(MyApplication.IMAGE_HOST + talentDetailInfo.getTalent().getHead_img())));
                    initChatListener();
                }
            }
        }
    
        /**
         * 会员详情
         */
        private class onMemberProflieXCallBack implements HttpHelper.XCallBack {
            @Override
            public void onResponse(String result) {
                UserInfo user = null;
                try {
                    user = getHttpResult(result, UserInfo.class);
                    user.setId(user.getUser());
    
                } catch (Exception e) {
                    Placard.showInfo(e.toString());
                }
                if (user != null) {
                    RongIM.getInstance().refreshUserInfoCache(new io.rong.imlib.model.UserInfo(String.valueOf(user.getUser()), user.getName(), Uri.parse(MyApplication.IMAGE_HOST + user.getMember().getHead_img())));
                    initChatListener();
                }
            }
        }
    
        /**
         * 邀单详情
         */
        private class onOrderInviteDetailXCallBack implements HttpHelper.XCallBack {
            @Override
            public void onResponse(String result) {
                OrderDetailInfo orderDetail = null;
                try {
                    orderDetail = getHttpResult(result, OrderDetailInfo.class);
                } catch (Exception e) {
                    showToastText(e.toString());
                }
                if (orderDetail != null) {
                    Intent intent = new Intent();
                    intent.putExtra("id", orderITextMsgMessage.getId());
                    intent.putExtra("status", orderITextMsgMessage.getStatus());
                    switch (orderITextMsgMessage.getStatus()) {
                        case 0:
                            if (orderDetail.getUser().getId() == MyApplication.getUserId()) {
                                intent.putExtra("viewtype", "aboutmaster");
                                if (orderITextMsgMessage.getId() != 0) {
                                    intent.putExtra("invite_order_id", orderITextMsgMessage.getId());
                                }
                                openActivity(intent, SearchListActivity.class);
                            } else {
                                openActivity(intent, OrderITextMsgDetailActivity.class);
                            }
                            break;
                        case 1:
                            openActivity(intent, OrderITextMsgDetailActivity.class);
                            break;
                        case 2:
                            openActivity(intent, OrderITextMsgDetailActivity.class);
                            break;
                        case 3:
                            openActivity(intent, OrderITextMsgDetailActivity.class);
                            break;
                    }
                }
            }
        }
    }
    

    融云的推送服务( 默认即可 )

    /**
     * 广播接收器
     */
    public class SealNotificationReceive extends PushMessageReceiver {
    
        @Override
        public boolean onNotificationMessageArrived(Context context, PushNotificationMessage message) {
            return false; // 返回 false, 会弹出融云 SDK 默认通知; 返回 true, 融云 SDK 不会弹通知, 通知需要由您自定义。
        }
    
        @Override
        public boolean onNotificationMessageClicked(Context context, PushNotificationMessage message) {
            return false; // 返回 false, 会走融云 SDK 默认处理逻辑, 即点击该通知会打开会话列表或会话界面; 返回 true, 则由您自定义处理逻辑。
        }
    }
    

    自定义消息类( 构造函数是通过ipc通道传输的 ,虽然没被调用 ,但是不可删除 )

    /**
     * 自定义消息类
     * 用户的审核状态(达人审核,实名认证审核)
     */
    @MessageTag(value = "User:TxtMsg", flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED)
    public class UserTextMsgMessage extends MessageContent {
        private String content;//消息属性,可随意定义
    
        /**
         * 构造函数。
         *
         * @param data 初始化传入的二进制数据。
         */
        public UserTextMsgMessage(byte[] data) {
            String jsonStr = null;
            try {
                jsonStr = new String(data, "UTF-8");
                Log.e("rongyun_user_message", jsonStr);
            } catch (UnsupportedEncodingException e1) {
                Placard.showInfo(e1.toString());
            }
    
            try {
                JSONObject jsonObj = new JSONObject(jsonStr);
                if (jsonObj.has("content"))
                    Log.e("content  :", jsonObj.optString("content"));
                setContent(jsonObj.optString("content"));
            } catch (JSONException e) {
                Log.e("rongyun_JSONException", e.getMessage());
            }
        }
    
        /**
         * 构造函数。
         *
         * @param in 初始化传入的 Parcel     */
        public UserTextMsgMessage(Parcel in) {
            setContent(ParcelUtils.readFromParcel(in));//该类为工具类,消息属性
        }
    
        /**
         * 读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。
         */
        public static final Creator<UserTextMsgMessage> CREATOR = new Creator<UserTextMsgMessage>() {
    
            @Override
            public UserTextMsgMessage createFromParcel(Parcel source) {
                return new UserTextMsgMessage(source);
            }
    
            @Override
            public UserTextMsgMessage[] newArray(int size) {
                return new UserTextMsgMessage[size];
            }
        };
    
        /**
         * 构建一个文字消息实例。
         *
         * @return 文字消息实例。
         */
        public static TextMessage obtain(String text) {
            return new TextMessage(text);
        }
    
        /**
         * 描述了包含在 Parcelable 对象排列信息中的特殊对象的类型。
         *
         * @return 一个标志位,表明Parcelable对象特殊对象类型集合的排列。
         */
        public int describeContents() {
            return 0;
        }
    
        /**
         * 将类的数据写入外部提供的 Parcel 中。
         *
         * @param dest  对象被写入的 Parcel     * @param flags 对象如何被写入的附加标志。
         */
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            //这里可继续增加你消息的属性
            ParcelUtils.writeToParcel(dest, getContent());
        }
    
        /*
        *
        * 实现 encode() 方法,该方法的功能是将消息属性封装成 json 串,
        * 再将 json 串转成 byte 数组,该方法会在发消息时调用,如下面示例代码:
        * */
        @Override
        public byte[] encode() {
            JSONObject jsonObj = new JSONObject();
            try {
                jsonObj.put("content", this.getContent());
            } catch (JSONException e) {
                Log.e("JSONException", e.getMessage());
            }
            try {
                return jsonObj.toString().getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
    }
    

    自定义消息模板

    /**
     * 自定义消息模板
     * <p>
     * desc新建一个消息类继承 IContainerItemProvider.MessageProvider 类,实现对应接口方法,
     * 注意开头的注解!
     * 注意泛型!
     * </p>
     */
    @ProviderTag(messageContent = UserTextMsgMessage.class, showPortrait = false, centerInHorizontal = true, showSummaryWithName = false)
    public class UserTextMsgMessageItemProvider extends IContainerItemProvider.MessageProvider<UserTextMsgMessage> {
        /**
         * //根据需求,适配数据
         *
         * @param view
         * @param i
         * @param userTextMsgMessage
         * @param uiMessage
         */
        @Override
        public void bindView(View view, int i, UserTextMsgMessage userTextMsgMessage, UIMessage uiMessage) {
            //根据需求,适配数据
            ViewHolder holder = (ViewHolder) view.getTag();
    //        if (uiMessage.getMessageDirection() == Message.MessageDirection.SEND) {//消息方向,自己发送的
    //            holder.user_content.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_right);
    //        } else {
    //            holder.user_content.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_left);
    //        }
            holder.user_content.setText(userTextMsgMessage.getContent());
        }
    
        @Override
        public Spannable getContentSummary(UserTextMsgMessage userTextMsgMessage) {
            return new SpannableString(userTextMsgMessage.getContent());
        }
    
        @Override
        public void onItemClick(View view, int i, UserTextMsgMessage userTextMsgMessage, UIMessage uiMessage) {
    
        }
    
        /**
         * 展示在会话界面的自定义的消息的布局
         *
         * @param context
         * @param viewGroup
         * @return
         */
        @Override
        public View newView(Context context, ViewGroup viewGroup) {
    //      这就是展示在会话界面的自定义的消息的布局
            View view = LayoutInflater.from(context).inflate(R.layout.user_message, null);
            ViewHolder holder = new ViewHolder();
            holder.user_content = (TextView) view.findViewById(R.id.user_content);
            view.setTag(holder);
            return view;
        }
    
        private static class ViewHolder {
            TextView user_content;
        }
    }
    


    闲聊群 :  668524118

    这里写的比较简单 ,

    如有不懂的地方 ,欢迎加群询问 .

    展开全文
  • 【融云SDK集成实现单聊App】

    千次阅读 2018-02-28 16:18:34
    本人菜鸟一枚,自学不才,在Android开发圈子也是摸打滚爬,3,4年,之前没有写博客的习惯,只是自己总结一些,没有分享。当然好多还是参考的大神们分享的东西,去github fork 别人的代码。。话不多说,开干!【1】...


    本人菜鸟一枚,自学不才,在Android开发圈子也是摸打滚爬,3,4年,之前没有写博客的习惯,只是自己总结一些,没有分享。当然好多还是参考的大神们分享的东西,去github fork  别人的代码。。

    话不多说,开干!

    【1】SDK的集成套路,注册登录SDK官网点击打开链接,下载SDK,看集成文档。

    【2】特别值得一提的是,融云的SDK,模块化很好,下载SDK时,可以先择需要集成的模块,见下图:

    IMKit SDK是融云做好的UI库,java代码封装成了jar,布局文件暴露,可以自己修改颜色样式。IMKit Module依赖IMLibModule。

    【3】导入AndroidStudio时,将IMKit及IMLIb都以Module的方式导入。



    然后app项目添加依赖module,只添加IMKit,即可。app的dependencies如下:


    【4】在IMLib的AndroidManifest.xml中将RONG_CLOUD_APP_KEY修改为自己在官网创建项目生成的appkey。

    (集成过SDK的都明白这一步!!!不赘述)


    【5】在自己项目的AndroidManifest.xml文件中添加FileProvider

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.bj.rongyundemo.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/rc_file_path" />
    </provider>


    需要注意的是authorities的值修改为"自己的包名.FileProvider"。至此融云的配置基本完成,可以进行开发了。
    【6】融云初始化,在自己的Application中定义。代码如下:
    public class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            if (getApplicationInfo().packageName.equals(getCurProcessName(getApplicationContext())) ||
                    "io.rong.push".equals(getCurProcessName(getApplicationContext()))) {
    
                /**
                 * IMKit SDK调用第一步 初始化
                 */
                RongIM.init(this);
            }
        }
        /**
         * 获得当前进程的名字
         *
         * @param context
         * @return 进程号
         */
        public static String getCurProcessName(Context context) {
    
            int pid = android.os.Process.myPid();
    
            ActivityManager activityManager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
    
            for (ActivityManager.RunningAppProcessInfo appProcess : activityManager
                    .getRunningAppProcesses()) {
    
                if (appProcess.pid == pid) {
                    return appProcess.processName;
                }
            }
            return null;
        }
    }


    【7】我写了一个有底部导航栏的主页面,一个好友列表,一个消息列表。效果如下:
    1----->>问友界面只有发消息的点击事件跟融云有关系,核心代码如下:

    holder.tv_send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
     // start chat acitivity
            if(RongIM.getInstance()!=null){
                RongIM.getInstance().startPrivateChat(mContext,"10010","联通");
            }
        }
    });



    startPrivateChart(a,b)是开启单聊的方式,参数a是聊天对方的id,参数b是聊天对方的昵称。
    2---->开始聊天之前必须先连接融云服务器,连接融云服务器的方式是必须拿到该APP的登录帐号在融云的token。
    这个token的获取需要通过ServerAPI来获取(此步需要APP服务端来做,省略)。这里我们通过融云的API调试,获取Token。
    先讲一下如何官网进行API调试,如下,点击已创建的应用,点API调试,点获取Toekn,拉到最下面输入用户id即可。

    获取到token之后,就可以进行连接融云服务器了。代码如下:

    /**
     * 建立与融云服务器的连接
     *
     * @param token
     */
    private void connect(String token) {
    
        if (getApplicationInfo().packageName.equals(App.getCurProcessName(getApplicationContext()))) {
    
            /**
             * IMKit SDK调用第二步,建立与服务器的连接
             */
            RongIM.connect(token, new RongIMClient.ConnectCallback() {
    
                /**
                 * Token 错误,在线上环境下主要是因为 Token 已经过期,您需要向 App Server 重新请求一个新的 Token
                 */
                @Override
                public void onTokenIncorrect() {
    
                    Log.e("tag", "--onTokenIncorrect");
                }
    
                /**
                 * 连接融云成功
                 * @param userid 当前 token
                 */
                @Override
                public void onSuccess(String userid) {
                    Log.e("tag", "--onSuccess" + userid);
                }
                /**
                 * 连接融云失败
                 * @param errorCode 错误码,可到官网 查看错误码对应的注释
                 */
                @Override
                public void onError(RongIMClient.ErrorCode errorCode) {
    
                    Log.e("tag", "--onError" + errorCode);
                }
            });
        }
    }


    连接成功后,会返回用户的id。

    3-------->>>>>>>>>>消息列表界面,使用IMKit提供的UI。初始化一个Fragment即可。如下:

    /**
     * 初始化会话列表
     * @return
     */
    private Fragment initConversationList() {
        if (frag_msg == null) {
            ConversationListFragment listFragment = new ConversationListFragment();
            Uri uri=Uri.parse("rong://"+getApplicationInfo().packageName).buildUpon()
                    .appendPath("conversationlist")
                    .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false") //设置私聊会话是否聚合显示
                    .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")//群组
                    .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")//系统
                    .appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")
                    .build();
            listFragment.setUri(uri);
            return  listFragment;
        }else{
           return frag_msg;
        }
    }


    【8】聊天界面编写,布局文件activity_chat.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            app:layout_collapseMode="pin"
            android:layout_height="?attr/actionBarSize"
            android:background="#4ececf"
            app:contentInsetStart="0dp">
    
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="聊天"
                android:textColor="@android:color/white"
                android:textSize="20sp" />
        </android.support.v7.widget.Toolbar>
        <fragment
            android:id="@+id/conversation"
            android:name="io.rong.imkit.fragment.ConversationFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>



    ChatActivity.class如下:

    public class ChatActivity extends FragmentActivity {
        @Bind(R.id.tv_title)
        TextView tvTitle;
        @Bind(R.id.toolbar)
        Toolbar toolbar;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_chat);
            ButterKnife.bind(this);
            //IM
            RongIM.getInstance().enableNewComingMessageIcon(true);//显示新消息提醒
            RongIM.getInstance().enableUnreadMessageIcon(true);//显示未读消息数目
            String targetId = getIntent().getData().getQueryParameter("targetId");
            String title = getIntent().getData().getQueryParameter("title");//必须实现内容提供者才能获取到title
            if(!TextUtils.isEmpty(title)){
                tvTitle.setText(title);
            }else{
                //根据id,去服务端请求用户信息,再设置
            }
    
        }
    }


    因为我们使用的是IMKit UI库的界面,只需要的在activity中包含一个conversationFragment即可。

    android:name="io.rong.imkit.fragment.ConversationFragment"
    
    
     RongIM.getInstance().enableNewComingMessageIcon(true);//显示新消息提醒
     RongIM.getInstance().enableUnreadMessageIcon(true);//显示未读消息
    这两行代码是是聊天界面的消息提示。
     String targetId = getIntent().getData().getQueryParameter("targetId");
     String title = getIntent().getData().getQueryParameter("title");//必须实现内容提供者才能获取到title
    targetid和title是问友界面,发送消息的事件中,startPrivate()方法中传过来的值。
    最后还有最关键的一步,在自己应用的AndroidManifest.xml中配置ChatActivity。
    配置如下:
    
    
    <activity android:name=".ChatActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data
                android:host="com.bj.rongyundemo"
                android:pathPrefix="/conversation/"
                android:scheme="rong" />
        </intent-filter>
    </activity>



    host修改为自己的包名。至此已经能够正常收发消息了。
    【9】消息推送,融云有自己的消息推送,当然也可以集成第三方推送,融云官方均有介绍。这里我们只做融云推送。
    1---->>写WenwenNotificationReceiver 
    public class WenwenNotificationReceiver extends PushMessageReceiver {
        @Override
        public boolean onNotificationMessageArrived(Context context, PushNotificationMessage message) {
            Log.e("tag","-------message------");
            return false; // 返回 false, 会弹出融云 SDK 默认通知; 返回 true, 融云 SDK 不会弹通知, 通知需要由您自定义。
        }
    
        @Override
        public boolean onNotificationMessageClicked(Context context, PushNotificationMessage message) {
            Log.e("tag","-------message------");
            return false; // 返回 false, 会走融云 SDK 默认处理逻辑, 即点击该通知会打开会话列表或会话界面; 返回 true, 则由您自定义处理逻辑。
        }
    }


    2------->>在自己的清单文件中配置WenwenNotificationReceiver :
    <receiver
        android:exported="true"
        android:name=".receiver.WenwenNotificationReceiver">
        <intent-filter>
            <action android:name="io.rong.push.intent.MESSAGE_ARRIVED" />
            <action android:name="io.rong.push.intent.MI_MESSAGE_ARRIVED" />
            <action android:name="io.rong.push.intent.MESSAGE_CLICKED" />
            <action android:name="io.rong.push.intent.MI_MESSAGE_CLICKED" />
        </intent-filter>
    </receiver>


    【10】消息数量的监听。在消息列表Fragment的底部tab,我们要显示收到未读消息的数量。这个需要的MainActivity中添加监听即可。
    /
    **
     * 融云未读消息监听
     */
    private void initUnreadCountListener() {
        final Conversation.ConversationType[] conversationTypes = {Conversation.ConversationType.PRIVATE, Conversation.ConversationType.DISCUSSION,
                Conversation.ConversationType.GROUP, Conversation.ConversationType.SYSTEM,
                Conversation.ConversationType.PUBLIC_SERVICE};
    
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                RongIM.getInstance().setOnReceiveUnreadCountChangedListener(mCountListener, conversationTypes);
            }
        }, 500);
    }
    public RongIM.OnReceiveUnreadCountChangedListener mCountListener = new RongIM.OnReceiveUnreadCountChangedListener() {
        @Override
        public void onMessageIncreased(int count) {
           Log.e("tag","count:" + count);
            if (count == 0) {
                tvTabBadge.setVisibility(View.GONE);
            } else if (count > 0 && count < 100) {
                tvTabBadge.setVisibility(View.VISIBLE);
                tvTabBadge.setText(count + "");
            } else {
                tvTabBadge.setVisibility(View.VISIBLE);
                tvTabBadge.setText("99+");
            }
        }
    };

    onCreate()方法中调用即可。
    【11】用户头像和昵称修改成用户自己的头像和昵称。两种方式。
    第一种方式是内容提供者:
    1-->在MainActivity的onCreate()方法中添加:
    RongIM.setUserInfoProvider(this,true);
    2---->实现该方法
    /**
     * 融云实现内容提供者,将用户信息提交给融云,融云在使用自己的SDK时,会加载自己的头像。昵称
     * @param userId
     * @return
     */
    
    @Override
    public UserInfo getUserInfo(String userId) {
        for (Friend  friend:friends){
            if(friend.getUserId().equals(userId)){
                return  new UserInfo(friend.getUserId(),friend.getUserName(),Uri.parse(friend.getAvator()));
            }
        }
        return null;
    }


    就是用户根据自己的id去获取用户昵称及头像,封装为融云的UserInfo即可。
    第二种方式是在用户连接融云服务器成功后,执行如下代码:
    if(RongIM.getInstance()!=null){
        //1、设置当前用户信息
        RongIM.getInstance().setCurrentUserInfo(new UserInfo(userid,friends.get(0).getUserName(),Uri.parse(friends.get(0).getAvator())));
        //2
        RongIM.getInstance().setMessageAttachedUserInfo(true);
    }

    //当A.b互通消息时,各端接收到消息后,SDK会自动从消息中取出用户信息放入用户信息缓存中,并刷新UI显示
    设置当前的用户信息,UserInfo是融云定义好的实体。
    -------------------至此,融云的单聊模式功能全部结束------------------------


    源代码及Apk下载

    接下来一段时间,会搞环信SDK,环信坑比较多。。。。



    展开全文
  • 最近项目中需要集成即时通讯,于是就选择了融云,相对来按照步骤说一步一步来还是很简单的,下面简单记录一下 一, ... 二,第二步下载SDK ,我是直接下载的IMKit,上边有介绍,能实现基本的功能,可根据自己的需求...

    最近项目中需要集成即时通讯,于是就选择了融云,按照步骤一步一步来还是很简单的,我做的只是单聊,(可支持发送文字、表情、图片、语音)下面记录一下
    先上图
    在这里插入图片描述

    步骤:

    一,去融云官网注册账号然后创建应用,应用创建完成后把自己的App Key记录下来 我们在配置的时候会用到**

    在这里插入图片描述

    二,第二步下载SDK ,我是直接下载的IMKit,上边有介绍,能实现基本的功能,可根据自己的需求下载

    在这里插入图片描述

    下载完是这样的
    在这里插入图片描述

    三,将IMKit和IMLib导入自己的项目中

    在这里插入图片描述
    这样就导进来了
    在这里插入图片描述

    最好也在App的build.gradle中看一下有没有引入

    在这里插入图片描述

    四,好了准备工作一切完毕,下面划重点,初始化融云。在整个应用程序中,只需要调用一次 init 方法。

    public class App extends BaseApplication {
        
        @Override
        public void onCreate() {
            super.onCreate();
          
            RongIM.init(this);
        }
    
    

    五,打开 IMLib Module 的 AndroidManifest.xml 文件,把RONG_CLOUD_APP_KEY的值修改为自己的 AppKey. 如图:

    在这里插入图片描述

    在应用的 App Module 的 AndroidManifest.xml 文件中,添加 FileProvider 相关配置,修改 android:authorities 为App 的应用的 “ApplicationId”.FileProvider。

    在这里插入图片描述

    六,连接融云,我是放在程序登录成功后执行的

    RongIM.connect(token, new RongIMClient.ConnectCallback() {
        /*
         * Token 错误。可以从下面两点检查
         * 1.  Token 是否过期,如果过期您需要向 App Server 重新请求一个新的 Token
         * 2.  token 对应的 appKey 和工程里设置的 appKey 是否一致
         */
        @Override
        public void onTokenIncorrect() {
            
        }
        /*
         * 连接融云成功
         * @param userid 当前 token 对应的用户 id
         * 
         */
        
        @Override
        public void onSuccess(String userid) {
            Log.d("LoginActivity", "融云连接成功!!!" + userid);
        }
        
        /*连接融云失败
         * @param errorCode 错误码,可到官网 查看错误码对应的注释
         */
    
        @Override
        public void onError(RongIMClient.ErrorCode errorCode) {
            Log.d("LoginActivity", "融云连接失败!!!" + errorCode);
        }
    });
    

    七,下面开始配置会话列表先来配置布局文件 注:name是固定不能修改的

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <fragment
            android:id="@+id/conversationlist"
            android:name="io.rong.imkit.fragment.ConversationListFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="12dp"/>
    </LinearLayout>
    

    在代码中

      ConversationListFragment listFragment = (ConversationListFragment) ConversationListFragment.instantiate(mContext, ConversationListFragment.class.getName());
    Uri uri = Uri.parse("rong://" + getActivity().getApplicationInfo().packageName).buildUpon()
            .appendPath("conversationlist")
            .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")
            .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")
            .appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")
            .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")
            .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")
            .build();
    listFragment.setUri(uri);
    FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
    //将融云的Fragment界面加入到我们的页面。
    transaction.add(R.id.conversationlist, listFragment);
    transaction.commitAllowingStateLoss();
    

    在AndroidManifest中,融云 SDK 是通过隐式调用的方式来实现界面跳转的,您的会话列表 Activity 下面配置 intent-filter,其中,android:host 是您应用的 ApplicationId,需要手动修改,其他请保持不变。

    <!-- 会话列表 -->
    <activity
        android:name=".activity.New_MainActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data
                android:host="替换成您的ApplicationId"
                android:pathPrefix="/conversationlist"
                android:scheme="rong" />
        </intent-filter>
    </activity>
    

    八,接下来是新建会话页面Activity

    布局文件中

     <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@drawable/bg_doctor_blue"
        android:elevation="3dp"
        >
        <ImageView
            android:id="@+id/back"
            android:layout_width="40dp"
            android:layout_height="match_parent"
            android:padding="10dp"
            android:src="@mipmap/back_white"/>
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="与  对话中"
            android:textSize="16sp"
            android:textColor="@color/bg_white"
            android:gravity="center"
            android:layout_centerInParent="true"/>
    </RelativeLayout>
    
    <fragment
        android:id="@+id/conversation"
        android:background="@color/bg_white"
        android:name="io.rong.imkit.fragment.ConversationFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    会话 Activity

     //设置自己的信息
    RongIM.getInstance().setCurrentUserInfo(new UserInfo(UserUtils.getUid(), UserUtils.getName(), Uri.parse(UserUtils.getHeader())));
    //与我聊天的人的名字
    String sName = getIntent().getData().getQueryParameter("title");//获取昵称
    //与我聊天的人的Uid
    String targetId = getIntent().getData().getQueryParameter("targetId");//获取对方id
    title.setText("与" + sName + " 对话中");
    

    配置 intent-filter 在 AndroidManifest.xml 中,会话 Activity 下面配置 intent-filter。 注意请修改 android:host 为您应用的 ApplicationId,其他保持不变。**

    <activity
        android:name=".activity.ConversationListActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="stateHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data
                android:host="替换成您的ApplicationId"
                android:pathPrefix="/conversation/"
                android:scheme="rong" />
        </intent-filter>
    </activity>
    

    写到这 基本的单聊功能就可以会实现了

    九,如何从别的页面点击跳转至会话页面呢

    //跳转到聊天页面 传入对方的id 和 名字
    RongIM.getInstance().startPrivateChat(context, TargetUserId, Title);
    

    十,记录一下按照我们需求要改的地方

    1,如何缓存用户的信息,则通过refreshUserInfoCache(注:如果有好友更换了头像,需通过refreshUserInfoCache来存储)

    RongIM.getInstance().refreshUserInfoCache(new UserInfo(list.get(Position).getUid() + "", list.get(Position).getName(), Uri.parse(list.get(Position).getAvatar())));
    

    2,融云默认头像是方的,如果要改成圆形则需要在IMKit中找到下边这三个文件

    	rc_item_conversation.xml 会话列表 
    	rc_item_message.xml 会话页面 
    	rc_item_conversation_member.xml 设置页面
    

    根据需求替换相应的属性, 每个文件有两处需替换

            //圆形
     	app:RCShape="circle"
     	android:scaleType="centerCrop"
     	//方形
     	app:RCShape="square"
    	android:scaleType="centerCrop"
    

    3, 如果需要修改聊天气泡的背景,换成自己的.9图, 则在IMKit文件夹中替换这些drawable文件

    	rc_ic_bubble_right.9.png			rc_ic_bubble_left.9.png
    	rc_ic_bubble_no_right.9.png			rc_ic_bubble_no_left.9.png
    	rc_ic_bubble_right_file.9.png			rc_ic_bubble_left_file.9.png 
    

    3,如果需要修改会话列表的样式则在R.layout.rc_item_conversation文件中按需求自定义就可以

    展开全文
  • 本人菜鸟一枚,自学不才,在Android开发圈子也是摸打滚爬,3,4年,之前没有写博客的习惯,只是自己总结一些,没有分享。当然好多还是参考的大神们分享的东西,去github fork&nbsp; 别人的代码。。话不多说,开...
  • 总是听到有人说AndroidX,到底什么是AndroidX?

    万次阅读 多人点赞 2019-08-26 08:06:59
    Android技术迭代更新很快,各种新出的技术和名词也是层出不穷。不知从什么时候开始,总是会时不时听到AndroidX这个名词,这难道又是什么新出技术吗?相信有很多朋友也会存在这样的疑惑,那么今天我就来写一篇科普...
  • AndroidX了解一下

    万次阅读 多人点赞 2019-10-14 17:16:46
    1.前言 我选取了几个常用依赖库,我们可以看看变化: ... AndroidX build artifact ... com.android.support:support-compat ... androidx.core:core:1.0.0+ ... com.android.support:appcompat-v7 ... androidx.appco...
  • android studio的安装,史上最详细(超多图)!!

    万次阅读 多人点赞 2020-02-24 11:04:32
    android studio的安装,史上最详细!!欢迎前来观看,感觉有用就点波关注吧!custom 欢迎前来观看,感觉有用就点波关注吧! 1、首先下载Android studio安装包,可以从 http://www.android-studio.org/ 下载最新...
  • 如果能在Android中使用离线的谷歌地图将是一件很爽的事情!按照如下步骤做吧!体验一下高潮来临的快感吧!哈哈!以下操作在windows下进行!安裝 Java 執行環境 (JRE 或 JDK,至少為 JRE v1.6.0_14 或更高版本)。...
  • Android简介及发展历程

    千次阅读 2020-07-30 19:43:50
    简介 Android是基于Linux系统的开源操作系统,是由Andy Rubin于2003年在美国加州创建,后被Google于2005年收购。在2008年的时候发布了第一部Android智能手机,随后Android不断发展更新,占据了全球大部分的手机市场...
  • Android简介

    千次阅读 多人点赞 2011-07-15 09:42:16
    Android简介一、用户角度 user’s perspectiveAndroid是一个操作系统,就像Windows一样,为用户和手机之间架起一道桥梁,协调和管理手机资源,让用户更方便的使用和控制手机硬件,如网络连接设备(Wifi, GPRS),...
  • Android入门教程 (一) Android简介和android studio安装

    千次阅读 多人点赞 2020-07-02 14:07:30
    写这篇文章,是为了让萌新们快速入门Android开发,同时讲述一下我对Android的理解,以及未来学习Android的规划,希望能够对大家有点参考价值。 Android是什么? Android就是跟苹果IOS一样,是一个操作系统。我们...
  • Android(一)-Android简介

    千次阅读 2012-10-29 15:10:19
    Android简介:  Android是基于Linux平台用Java语言开发的一种开放源代码的手机操作系统。  Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台...
  • ANDROID 一个开源的手机联盟项目 什么是ANDROIDANDROID是一个专用于移动设备的软件系统,它包括操作系统,中间件和关键应用,初略了解一下Android SDK提供必要的工具和API在Android平台上使用Java语言来开发应用
  • [002] Android系统简介

    万次阅读 2011-04-22 22:34:00
    Android简介Android是基于Linux内核的操作系统,是Google公司于2007年11月5日公布的智能手机操作系统,该平台由操作系统、中间件、用户界面和应用软件组成,号称是首个为移动终端打造的真正开放和完整的移动软件。...
  • Kotlin是众多基于JVM的语言之一,它一开始是作为android 开发中java语言的可能的代替者出现的。java是世界上使用最多的语言之一,而伴随着其他语言的发展使得程序员编程越来越容易,
1 2 3 4 5 ... 20
收藏数 87,885
精华内容 35,154
关键字:

android