Android开发--IM聊天项目(四)--IPC实战

Android端与Java服务端交互——SocketIO 最近,由于工作需要,老哥我被分配了研究Android客户端和Java服务端利用SocketIO进行通讯。原先的产品通信是基于js和java的,html5+js作为客户端,服务端用netty-socketio实现的,老大来需求了,说那啥啥啥,咱把这个客户端的通讯部分用Android原生的实现,不要基于js实现,我来了句为啥呀?答:js通讯 不是太稳定(由于我对前端几乎是没有了解,也没有JS相关的经历, 阅读详情

花了两天重写学习了一下IPC、binder等相关知识,于是决定把这个聊天项目也重构一下,让聊天的service功能单独在一个进程,一个是为了更加稳定,对内存的控制也能更加合理,使应用常驻后台,防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。 Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。 典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。

下面放代码

// IChatManager.aidl
package com.sp.chattingroom;
// Declare any non-default types here with import statements
import com.sp.chattingroom.Model.Msg;
import com.sp.chattingroom.I_NewMessageArrived;
import com.sp.chattingroom.I_GetLoginResult;
interface IChatManager {
    void registerNewMsgListener(I_NewMessageArrived listener);
    void registerLoginResultListener(I_GetLoginResult listener);
    void Login(in String name,I_GetLoginResult listener);
    void SendMsg(in Msg msg);
}
// I_NewMessageArrived.aidl
package com.sp.chattingroom;

// Declare any non-default types here with import statements
import com.sp.chattingroom.Model.Msg;
interface I_NewMessageArrived {
    void newMessageArrive(in Msg msg);
}
// I_GetLoginResult.aidl
package com.sp.chattingroom;

// Declare any non-default types here with import statements

interface I_GetLoginResult {  
    void loginSucceed();
    void loginFailed();
}

注释上写了文件名字。
然后build之后就会生成了三个IInterface的类,就是进程通信的关键了,接下来就会利用他们的Binder来实现IPC。
然后是Service的改造

package com.sp.chattingroom.Service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.github.nkzawa.emitter.Emitter;
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
import com.sp.chattingroom.IChatManager;
import com.sp.chattingroom.I_GetLoginResult;
import com.sp.chattingroom.I_NewMessageArrived;
import com.sp.chattingroom.Model.Msg;

import java.net.URISyntaxException;

/**
 * Created by Administrator on 2017/2/20.
 */

public class ChatService extends Service {
    private static final String TAG = "ChatService";
    private Socket socket=null;
    private I_GetLoginResult i_getLoginResult;
    private I_NewMessageArrived i_newMessageArrived;
    private Binder mBinder=new IChatManager.Stub(){
        @Override
        public void SendMsg(Msg msg) throws RemoteException {
            socket.emit("postMsg",msg.getContent());
        }
        @Override
        public void Login(String name, final I_GetLoginResult listener) throws RemoteException {
            i_getLoginResult=listener;
            socket.emit("login",name);
            socket.on("nickExisted", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG, "nickExisted" );
                    try {
                        listener.loginFailed();
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                }
            });
            socket.on("loginSuccess",new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG, "loginSuccess:"+Thread.currentThread().getId());
                    try {
                        listener.loginSucceed();
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                }
            });
        }

        @Override
        public void registerNewMsgListener(I_NewMessageArrived listener) throws RemoteException {
            i_newMessageArrived=listener;
        }
        @Override
        public void registerLoginResultListener(I_GetLoginResult listener) throws RemoteException {
            i_getLoginResult=listener;
        }
    };
    @Override
    public void onCreate(){
        super.onCreate();
        /*
         *在这里初始化socket链接
         */
        try {
            socket= IO.socket("http://115.159.38.75:3000");
            socket.connect();
        }catch (URISyntaxException e){
            Log.e(TAG, "run: "+"error" );
            e.printStackTrace();
        }
        while (!socket.connected()){}
        socket.on("newMsg", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String newcontent=args[1].toString();
                try {
                    i_newMessageArrived.newMessageArrive(new Msg(0,newcontent));
                }catch (RemoteException e){
                    e.printStackTrace();
                }
            }
        });
    }
    @Override
    public int onStartCommand(Intent i,int flags,int startId){
        Log.e(TAG, "onStartCommand: " );
        return super.onStartCommand(i,flags,startId);
    }
    @Override
    public void onDestroy(){
        /*
         *关闭连接,停止监听
         */
        super.onDestroy();
        while (socket.connected()){
            socket.disconnect();
        }
        socket.off();
        Log.e(TAG, "onDestroy: "+socket.connected());
    }
    @Override
    public IBinder onBind(Intent intent){
        return mBinder;
    }
}

然后是LoginActivity

package com.sp.chattingroom;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.sp.chattingroom.base.LogUtil;
import com.sp.chattingroom.Service.ChatService;

import butterknife.BindView;
import butterknife.ButterKnife;
/**
 * Created by Administrator on 2017/2/21.
 */
public class LoginActivity extends Activity {
    @BindView(R.id.btn_login)Button button;
    @BindView(R.id.edt_username)EditText editText;
    private static final String TAG = "LoginActivity";
    private IChatManager mRemoteManager;
    private I_GetLoginResult mResultListener=new I_GetLoginResult.Stub(){
        @Override
        public void loginSucceed() throws RemoteException {
            LogUtil.log(TAG,"log suc");
            Intent intent=new Intent(LoginActivity.this,ChatActivity.class);
            startActivity(intent);
            finish();
        }
        @Override
        public void loginFailed() throws RemoteException {
            handler.obtainMessage().sendToTarget();
        }
    };
    private ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogUtil.log(TAG,"onServiceConnected");
            mRemoteManager=IChatManager.Stub.asInterface(service);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteManager=null;
            LogUtil.log(TAG,"onServiceDisconnected");
        }
    };
    @Override
    protected void onCreate(Bundle s){
        super.onCreate(s);
        setContentView(R.layout.loginactivity);
        ButterKnife.bind(this);
        Intent service=new Intent(this,ChatService.class);
        bindService(service,serviceConnection,BIND_AUTO_CREATE);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name=editText.getText().toString();
                try {
                    mRemoteManager.Login(name, mResultListener);
                }
                catch (RemoteException e){
                    e.printStackTrace();
                }
            }
        });
    }
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message message){
            editText.setText("");
            Toast.makeText(LoginActivity.this,"用户名重复",Toast.LENGTH_SHORT).show();
        }
    };
    @Override
    protected void onStart(){
        LogUtil.log(TAG,"onStart");
        super.onStart();
    }
    @Override
    protected void onResume(){
        LogUtil.log(TAG,"onResume");
        super.onResume();
    }
    @Override
    protected void onPause(){
        LogUtil.log(TAG,"onPause");
        super.onPause();
    }
    @Override
    protected void onStop(){
        LogUtil.log(TAG,"onStop");
        super.onStop();
    }
    @Override
    protected void onRestart(){
        LogUtil.log(TAG,"onRestart");
        super.onRestart();
    }
    @Override
    protected void onDestroy(){
        LogUtil.log(TAG,"onDestroy");
        super.onDestroy();
        unbindService(serviceConnection);
    }
    @Override
    protected void onSaveInstanceState(Bundle outState){
        LogUtil.log(TAG,"onSaveInstance");
        super.onSaveInstanceState(outState);
    }
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState){
        LogUtil.log(TAG,"onRestoreInstance");
        super.onSaveInstanceState(savedInstanceState);
    }
    @Override
    public void onConfigurationChanged(Configuration configuration){
        super.onConfigurationChanged(configuration);
        LogUtil.log(TAG,"onConfigurationChanged:"+configuration.orientation);
    }
}

ChatActivity

package com.sp.chattingroom;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.github.nkzawa.socketio.client.Socket;
import com.sp.chattingroom.Adapter.ChatRecyclerAdpter;
import com.sp.chattingroom.Adapter.DBHelper;
import com.sp.chattingroom.base.LogUtil;
import com.sp.chattingroom.Model.Msg;
import com.sp.chattingroom.Service.ChatService;

import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ChatActivity extends AppCompatActivity {
    private static final String TAG = "ChatActivity";
    @BindView(R.id.text_list)RecyclerView recyclerView;
    @BindView(R.id.send_btn)Button button;
    @BindView(R.id.chat_edit)EditText editText;
    private static String IPAddress="115.159.38.75";
    private static int PORT=4000;
    private Socket socket=null;
    private ChatRecyclerAdpter adpter;
    private ArrayList<Msg> msg_list=new ArrayList<>();
    private DBHelper dbHelper;
    private Cursor cursor;
    private Thread thread;
    private NotificationManager notificationManager;
    private IChatManager iChatManager;
    private I_NewMessageArrived i_newMessageArrived=new I_NewMessageArrived.Stub(){
        @Override
        public void newMessageArrive(Msg msg) throws RemoteException {
            Log.e(TAG, "newMsg: "+msg.getContent());
            SendNotification(msg.getContent());
            msg_list.add(msg);
            dbHelper.insert(msg);
            cursor.requery();
            Message.obtain(handler).sendToTarget();
        }
    };
    private ServiceConnection connection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogUtil.log("from util","onServiceConnected: "+name.toString());
            iChatManager=IChatManager.Stub.asInterface(service);
            try {
                iChatManager.registerNewMsgListener(i_newMessageArrived);
            }catch (RemoteException e){
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            LogUtil.log(TAG, "onServiceDisconnected: "+name.toString());
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chatactivity);
        ButterKnife.bind(this);
        notificationManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        dbHelper=new DBHelper(this);
        cursor=dbHelper.select();
        for (int i=0;i<cursor.getCount();i++){
            cursor.moveToPosition(i);
            Msg msg=new Msg(cursor.getInt(2),cursor.getString(1));
            //msg.setContent(cursor.getString(1));
            //msg.setType(cursor.getInt(2));
            msg_list.add(msg);
        }
        adpter=new ChatRecyclerAdpter(this,msg_list);
        LinearLayoutManager manager=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(adpter);
        //绑定service
        Intent startservice=new Intent(this,ChatService.class);
        bindService(startservice,connection,BIND_AUTO_CREATE);

        recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                recyclerView.scrollToPosition(msg_list.size()-1);
            }
        });
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String msg_send=editText.getText().toString();
                //binder.sendMSg(msg_send);
                Msg msg=new Msg(1,msg_send);
                try {
                    iChatManager.SendMsg(msg);
                }catch (RemoteException e){
                    e.printStackTrace();
                }
                //msg.setType(1);
                //msg.setContent(msg_send);
                msg_list.add(msg);
                dbHelper.insert(msg);
                cursor.requery();
                Message.obtain(handler).sendToTarget();
                editText.setText("");
            }
        });
    }
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message message){
            adpter.notifyDataSetChanged();
            recyclerView.scrollToPosition(msg_list.size()-1);
        }
    };
    private void SendNotification(String content){
        LogUtil.log(TAG, "SendNotification: "+content );
        /*这里要注意一个细节。
         *如果当前Activity存在的话,不应该再create一个新的活动,应该是回到当前活动。
         * 所以要给Intent添加对应的flag
         */
        Intent i=new Intent(Intent.ACTION_MAIN);
        i.addCategory(Intent.CATEGORY_LAUNCHER);
        i.setComponent(new ComponentName(this,ChatActivity.class));
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        PendingIntent p=PendingIntent.getActivity(this,0,i,0);
        Notification notification=new Notification.Builder(this)
                .setAutoCancel(true)
                .setContentText(content)
                .setContentTitle("新消息")
                .setTicker("Ticker")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setDefaults(Notification.DEFAULT_SOUND)
                .setContentIntent(p)
                .build();
        notificationManager.notify(0,notification);
    }
    @Override
    public void onDestroy(){
        unbindService(connection);
        super.onDestroy();
        Log.e(TAG, "onDestroy");
    }
    @Override
    public void onBackPressed(){
        Intent home = new Intent(Intent.ACTION_MAIN);
        home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        home.addCategory(Intent.CATEGORY_HOME);
        startActivity(home);
    }
}

下一阶段目标:

  • 继续实现断线重连。。。
  • 同时搭建推送平台
  • 进程保活,互相拉活的学习。
安卓Java面试题11-20 但是在北美市场,最大的两家运营商乃AT&T和Verizon,而目前所知取得Android手机销售权的仅有 T-Mobile和Sprint,其中T-Mobile的3G网络相对于其他三家也要逊色不少,因此,用户可以买账购买G1,能否体验到最佳的3G网络服务则要另当别论了!但是这样做同样不完美。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。 阅读详情

相关推荐

多进程聊天室

1. 客户端代码实现用户的输入和显示(包括其他客户端发送的消息) 2. 服务器端采用多进程的方式,运用共享内存实现消息的同步共享 3. 在linux下,亲测可运行, 4. 代码供参见

30分钟小Demo,基于Socket套接字实现即时通信IM

文章目录简介效果图服务端客户端(移动端) 简介 服务端基于Java Socket实现,代码开源见Github,其原理也很简单,A点击幸运数字发起请求与服务器建立Socket连接,B如果点击了相同的幸运数字,那么这两个人就算匹配成功,双方就可以聊天!都是通过服务器做转发来实现! 效果图 先来看一下效果图! 服务端 Server类:这个类的作用是负责与客户端建立连接、匹配、为用户分配ID等主要作用 class Server { private ServerSocket serverSocke

两行代码 踏踏实实de工作 4691

用SuperWebSocket框架实现的WebSocket服务端Demo源码

SuperWebSocket是基于.NET开源Socket框架SuperSocket开发的, SuperSocket所支持的大部分功能在SuperWebSocket中得到了继承。用户可通过SuperWebSocket来快速的构建可靠的,高性能的websocket服务器端应用程序。 和SuperSocket一样,SuperWebSocket可以控制台和windows服务的形式运行,同时它还支持直接运行在Website之内,这样更简化了用户的部署

SuperSocket 入门,实现客户端和服务端消息互发

源码地址:https://download.youkuaiyun.com/download/weixin_35196633/10151210 运行出来效果如下: 服务端: 客户端: 第一步,使用SuperSocket创建一个服务端 a.引入需要dll文件,由于supersocket使用到了log4,所以在这儿也需要引用log4net.dll 添加项目引用即可 b.创建一个...

诗书的博客 1万+

supersocket实现的聊天

supersocket实现的聊天

使用开源的supersocket实现的路灯模拟通信

使用一个开源的套接字通信框架(supersocket)来实现的模拟路灯通信的控制系统。 有兴趣研究套接字和supersocket相关技术的人士可以下载下来参考一下。

Android IPC机制

线程:线程是CPU调度的最小单位,是一种有限的系统资源。 进程:进程一般指一个执行单元,在PC或者移动设备上指一个程序或者应用。 一个进程可以包含多个线程,最简单情况下,一个进程只包含一个线程(即主线程)。Android中主线程也叫作UI线程。

xiaokangss的博客 1307

Android即时聊天app端 AS项目源码

Androidstudio版本的 即时聊天程序 经过修改 已经能支持离线模式 能够显示和图灵机器人的 各种聊天文件 否则需要修改和部署http(文件服务) java服务端 和oracle数据库 来支持数据展示

android安卓使用socketIO实现聊天室功能

代码示例,暂时先保存 引入: compile('io.socket:socket.io-client:1.0.0') { exclude group: 'org.json', module: 'json' } 基本使用: package com.leying.livestreaming.ui.activtiy; import android.Manifest; import android.annotation.SuppressLint; import andr.

jifenglie的博客 3714

别再问“这游戏啥引擎做的”了,手把手教你用SteamDB一键查询(附实战案例)

本文详细介绍了如何使用SteamDB一键查询游戏引擎信息,包括Unity 3D、Unreal Engine等热门引擎的识别方法。通过实战案例和高级查询技巧,帮助玩家快速获取游戏技术底细,优化游戏体验和兼容性分析。

weixin_31412781的博客 816

STM32F4XX软件模拟I2C实现MPU6050姿态数据采集

本文详细介绍了在STM32F4XX平台上通过软件模拟I2C驱动MPU6050传感器实现姿态数据采集的完整方案。内容涵盖软件I2C的GPIO配置、核心通信函数实现、MPU6050寄存器配置详解以及数据读取处理流程,为硬件资源受限的嵌入式应用提供了灵活的解决方案,并分享了调试技巧与常见问题处理方法。

butter的博客 677

Android Binder机制浅析及AIDL的使用

参考 轻松理解 Android Binder,只需要读这一篇 图文详解 Android Binder跨进程通信的原理 Android中的Parcel是什么 Android Binder IPC通信机制对比   前言 Android中有很多种IPC通信机制,如共享内存、管道、socket等。 Linux中的内存管理中存在虚拟内存和物理内存两种概念;每个进程都拥有自己独立的虚拟内存空间...

Ares 1383

Vertx之Grpc消息发送

介绍 Vert.x gRPC 模块,它将 Google gRPC 的编程风格与 Vert.x 风格保持一致. gRPC 是一个高性能、开源、通用的RPC框架,是一种进程间通讯技术,由Google推出,基于HTTP2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。gRPC提供了一种简单的方法来精确的定义服务,并且为客户端和服务端自动生成可靠的功能库。 在gRPC客户端可以直接调用不同服务器上的远程程序,使用姿势看起来就像调用本地程序一样,轻松的实现远端服务的连接、

Lance 1188

2024年安卓最全Android 直播中弹幕、带货和键盘的交互,2024年最新安卓面试准备

(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总)面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,

2401_84556480的博客 978

黑金AXU9EG开发板深度学习部署全流程解析

本文详细解析了黑金AXU9EG开发板的深度学习模型部署全流程,从环境搭建、模型转换到上板验证,提供了实用的技术指导和优化技巧。该开发板基于Xilinx Zynq UltraScale+ MPSoC架构,特别适合边缘计算场景,通过FPGA加速实现高效AI推理。

weixin_29062613的博客 447

Trae+Playwright MCP自动化测试全流程指南:从环境搭建到智能体运行

本文提供了一份详细的Trae与Playwright MCP集成指南,涵盖从Node.js、Python环境搭建到智能体创建的全流程。通过结合MCP协议,AI智能体能够理解任务并驱动Playwright执行复杂的浏览器自动化操作,实现从网页数据抓取到端到端测试的智能工作流。

banana的博客 531

Android消息内存优化实战与性能提升策略

消息处理是移动开发中的基础技术,通过消息队列机制实现线程间通信。其内存管理直接影响应用性能,特别是在高频消息场景下,不当处理会导致内存激增和GC频繁触发。从技术原理看,Message对象包含基础字段和可变Bundle数据,采用对象池模式可减少80%内存分配开销。工程实践中,结合分页加载和内存映射技术能有效控制大消息内存占用,而通过Memory Profiler工具可精准定位泄漏点。在IM、游戏同步等典型场景中,优化后的消息系统可使内存占用降低50%以上,同时提升帧率稳定性。本文以社交应用为案例,详解如何通过

cneo2012的博客 402

深入解析ISO12233标准:SFR算法从理论到代码实现

本文深入解析ISO12233标准中的SFR算法,从理论到代码实现全面介绍如何量化成像系统的解析力。通过e-SFR算法测量边缘扩散函数(ESF)和空间频率响应(SFR),结合光学原理和实际代码示例,帮助开发者准确评估影像质量。文章包含关键步骤的Python实现和工程优化技巧,适用于相机测试、镜头评估等应用场景。

weixin_29200485的博客 154

安卓开发面试问题,你的技术真的到天花板了吗?架构师必备技能

起因 事情是这样的。 4年前毕业那会,呆在公司的短视频项目,做 视频。那会做得比抖音还早,但是由于短视频太烧钱了,项目被公司关掉了。当时需要开发横竖屏直播/异步视频的场景,就研究下了市场上的 app,发现输入弹幕的交互并不友好。最直接的体验就是,微信比绝大部分IM软件在聊天场景下输入法与表情面板频繁切换时表现得更为平滑,不会给用户很突兀的闪烁感。但我们除了适配竖屏,们还需要兼容横屏/满屏/沉浸等场景。 摸索了一段时间之后,做出来的效果挺不错,比市面上的直播/异步视频播放场景下的输入交互体验都要好。于是写了个

m0_56130999的博客 145

实现两端固支梁热力耦合的有限元分析

在本文中,我们将使用Matlab实现两端固支梁的热力耦合有限元分析。我们假设梁的材料是均匀的,梁的截面积为1,长度为1,两端固支,且受到均匀分布的热荷载。接下来,我们需要组装全局刚度矩阵和热传导矩阵。对于两个相邻的元素,它们共享一个节点,因此需要使用连接矩阵将局部矩阵组装成全局矩阵。接下来,我们需要定义元素刚度矩阵和热传导矩阵。然后,我们需要定义载荷向量。然后,我们需要定义边界条件。在这个例子中,梁的两端固支,因此我们需要将两端节点的位移限制为0。最后,我们需要解决线性方程组,得到节点的位移和温度分布。

CyberSparkZ的博客 395

ESP32 WIFI 智能巡线小车设计与实现(四足 / 四轮通用)

本文设计的 ESP32 WIFI 智能巡线小车,硬件模块化、软件轻量化,兼容四足与四轮两种结构,实现了自动巡线与 WIFI 远程控制双功能。系统成本低、易上手,适合嵌入式初学者学习 WIFI 通信、传感器应用、运动控制等核心知识点,也可在此基础上扩展蓝牙控制、避障、视觉识别等功能。

weixin_42300449的博客 151

Android NotificationCompat 与 PendingIntent 深度解析:3种点击事件传递与数据回传方案

本文深入解析Android中NotificationCompat与PendingIntent的三种点击事件传递与数据回传方案,涵盖getActivity、getBroadcast和getService的使用场景与最佳实践。通过详细代码示例和Flag选择策略,帮助开发者高效处理通知栏交互,提升用户体验。

cuiyingchan0663的博客 400

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Android快速转战Kotlin教程,全套教学资料

起因 事情是这样的。 4年前毕业那会,呆在公司的短视频项目,做 视频。那会做得比抖音还早,但是由于短视频太烧钱了,项目被公司关掉了。当时需要开发横竖屏直播/异步视频的场景,就研究下了市场上的 app,发现输入弹幕的交互并不友好。最直接的体验就是,微信比绝大部分IM软件在聊天场景下输入法与表情面板频繁切换时表现得更为平滑,不会给用户很突兀的闪烁感。但我们除了适配竖屏,们还需要兼容横屏/满屏/沉浸等场景。 摸索了一段时间之后,做出来的效果挺不错,比市面上的直播/异步视频播放场景下的输入交互体验都要好。于是写了个

m0_56169789的博客 125

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

实现原理讲解!想给金三银四找工作的程序员几点建议,社招面试心得

起因 事情是这样的。 4年前毕业那会,呆在公司的短视频项目,做 视频。那会做得比抖音还早,但是由于短视频太烧钱了,项目被公司关掉了。当时需要开发横竖屏直播/异步视频的场景,就研究下了市场上的 app,发现输入弹幕的交互并不友好。最直接的体验就是,微信比绝大部分IM软件在聊天场景下输入法与表情面板频繁切换时表现得更为平滑,不会给用户很突兀的闪烁感。但我们除了适配竖屏,们还需要兼容横屏/满屏/沉浸等场景。 摸索了一段时间之后,做出来的效果挺不错,比市面上的直播/异步视频播放场景下的输入交互体验都要好。于是写了个

clhcowboy的博客 292

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

字节跳动8年老Android面试官经验谈,专题解析

起因 事情是这样的。 4年前毕业那会,呆在公司的短视频项目,做 视频。那会做得比抖音还早,但是由于短视频太烧钱了,项目被公司关掉了。当时需要开发横竖屏直播/异步视频的场景,就研究下了市场上的 app,发现输入弹幕的交互并不友好。最直接的体验就是,微信比绝大部分IM软件在聊天场景下输入法与表情面板频繁切换时表现得更为平滑,不会给用户很突兀的闪烁感。但我们除了适配竖屏,们还需要兼容横屏/满屏/沉浸等场景。 摸索了一段时间之后,做出来的效果挺不错,比市面上的直播/异步视频播放场景下的输入交互体验都要好。于是写了个

m0_57066131的博客 208

知识图谱与demo

这是一个视频画面安卓端到端投屏软件这是一个单个屏幕分屏效果的摄像头效果。在线电台是一个使用喜马拉雅在线电台SDK的免费api做成的一个在线听电台应用。具有推荐、订阅、历史、模糊搜索、播放控制(播放、暂停、按纽上下曲、滑动上下曲、列表模式切换、排序切换)、进度条、播放列表、订阅功能、电台节目详情页、ID3 信息专辑图展示、mini 播放器等功能。空间众包任务分配算法有打车、外卖配送等实际应用场景。

mix39的博客 2059
上一篇: 春风十里不如你、与IPC的邂逅
下一篇: Android开发--IM聊天项目(五)--进程保活踩坑
CallMeSP
博客等级 码龄10年 48粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值