安卓大作业——飞鸽传书(高仿微信)

产品介绍 项目背景 随着网络的出现,即时通讯软件便出现在了人们的生活中,即时通讯app可以帮助人们实现快速沟通,节省时间,提高效率。例如,团队成员可以在办公室或出差途中随时通过即时通讯app进行实时讨论和共享资源,避免沟通障碍,增进沟通的质量和效果。 技术框架 本次的软件开发主要以Java编程环境为主,在手机端编写安卓原生APP,在服务器后端使用SpringBoot框架为主,实现用户消息的转发和暂存,用户头像的上传与保存。 在软件的后端实现上,我使用SpringBoot框架,目的是使得产品的后期功能开发更加轻松,同时使用SpringBoot可以将服务端一键打包成jar包,简化服务器部署的复杂度。用户的头像使用腾讯云的对象存储保存,免去了调试与实际运行时头像存储位置不一致的问题,同时文件保存的可靠性和安全性也得到加强。 功能介绍 登录功能介绍 本次开发的APP与大部分软件不同,为保证软件的私密性,我们采用最小云端保存的方案,即将用户的数据尽量的放在本地,仅仅上传必须的内容。 用户初次使用本软件,软件会引导用户完成昵称和个性签名的配置,配置完成之后,系统会通过使用安卓的API生成一个几乎唯一的AndroidID作为用户的唯一ID。至此用户的ID基本信息就设置完成了。 头像上传 为保证更好的美观以及用户的体验,我们的软件可以自定义头像,用户可以从自己相册或者文件中选择一个自己喜欢的照片作为自己的头像。选择完成之后,软件便会上传头像,进入到欢迎界面。 扫一扫添加好友 使用扫一扫添加好友,在另一部手机的我的界面点击二维码的小图标,进入名片界面,使用另一部手机APP中的扫一扫功能扫描名片上的二维码,即可添加对方为好友。 好友聊天 选择一个好友,点击该好有,选择发消息,进入到聊天界面,在聊天框输入消息,点击发送,好友便会收到消息,并收到通知(需要打开通知权限)。 更换聊天背景 进入我的界面,点击关于,在关于界面中点击摇一摇更换头像开关,返回到聊天界面,摇一摇手机即可切换软件内部自带的聊天背景,此时去关于界面关闭摇一摇切换聊天背景,即可固定当前的聊天背景。 清空聊天记录 在消息界面,长按消息,软件会弹出一个界面您可以选择不显示该聊天,或者删除该聊天。 删除好友 在好友界面,点击任意好友,选择删除好友,再次确认,即可删除该好友,好友删除后,对方的好友列表中自己并不会消失,对方给自己发送的消息自己将无法收到。 技术实现 本次软件的核心功能便是用户消息的转发与暂存,网络的状况千变万化,如何保证消息能够被正确的接收和发送,避免消息被漏掉以及消息的实时性都是我们要关注的重点。 消息的封装 为保证消息的完整性和后期修改的灵活行,我们将消息封装在一个实体类中,并将该类序列化以便在Socket上传输。 package cn.shilight.myapplication.message; import java.io.Serializable; public class MessagObtian implements Serializable { private static final long serialVersionUID = 7471391170055841173L; public String getForUid() { return forUid; } public void setForUid(String forUid) { this.forUid = forUid; } public String getFromUid() { return fromUid; } public void setFromUid(String fromUid) { this.fromUid = fromUid; } private String forUid; private String fromUid; private int messageType; public int getMessageType() { return messageType; } public void setMessageType(int messageType) { this.messageType = messageType; } private String content ; final static int Tap = 0; final static int Text = 1; public MessagObtian(String forUid, String fromUid, int messageType) { // TODO Auto-generated method stub this.forUid = forUid; this.fromUid = fromUid; this.messageType = messageType; } public String getContent() { return content; } public MessagObtian setContent(String content) { this.content = content; return this; } } 图表 2消息类 ...

June 29, 2023 · 3 min · 晚晴

安卓之Service简单实现

Service 简介 Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。 生命周期 在安卓的Service 中,有两种类型的srevice 一种是直接通过 startService 启动的servic 其生命周期不受 Activity 的限制,另一种Service 是和Activity 绑定的服务,其生命周期收到与之绑定的 使用服务实现简单音乐播放器 权限声明 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 允许写手机存储(必须) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> 界面代码 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/paly" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="92dp" android:layout_marginTop="192dp" android:text="播放" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="192dp" android:layout_marginEnd="104dp" android:text="暂停" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="92dp" android:ems="10" android:inputType="text" android:text="音乐地址" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.457" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> MainActivity.java ...

April 19, 2023 · 2 min · 晚晴

安卓实现对RECYCLERVIEW中对ITEM的监听

在安卓中使用RecyclerView 无法实现直接的item监听,需要自己写一个监听的类 创建监听类 public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener { private GestureDetector gestureDetector; private ClickListener clickListener; public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) { this.clickListener = clickListener; gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null && clickListener != null) { clickListener.onLongClick(child, recyclerView.getChildPosition(child)); } } }); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { View child = rv.findChildViewUnder(e.getX(), e.getY()); if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { clickListener.onClick(child, rv.getChildPosition(child)); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } public interface ClickListener { void onClick(View view, int position); void onLongClick(View view, int position); } } 使用你创建的类 recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), recyclerView, new RecyclerTouchListener.ClickListener() { @Override public void onClick(View view, int position) { Toast.makeText(getContext(),String.valueOf(position),Toast.LENGTH_LONG).show(); } @Override public void onLongClick(View view, int position) { Toast.makeText(getContext(),"长按操作",Toast.LENGTH_LONG).show(); } }));

March 24, 2023 · 1 min · 晚晴

安卓 之 HTTP 访问

安卓 之 HTTP 访问 package cn.shilight.shiguang; import android.util.Log; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class http { String result = "{\"result\":\"10002\"}"; public String POST(String url,String data){ try { URL wz = new URL(url); try { HttpURLConnection HTTP= (HttpURLConnection) wz.openConnection(); HTTP.setDoOutput(true); HTTP.setDoInput(true); HTTP.setRequestMethod("POST"); HTTP.setConnectTimeout(3000); HTTP.setUseCaches(false); HTTP.setRequestProperty("Accept-Encoding","identity"); OutputStream outputStream = HTTP.getOutputStream(); outputStream.write(data.getBytes()); int code = HTTP.getResponseCode(); //获得服务器的响应码 Log.i("服务器:", String.valueOf(code)); InputStream inputStream=HTTP.getInputStream();//获取服务器返回输入流 BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response=new StringBuilder(); String line; while ((line=reader.readLine())!=null){ response.append(line); } result = (response.toString()); } catch (IOException e) { e.printStackTrace(); return result; } } catch (MalformedURLException e ){ e.printStackTrace(); return result; }finally { } return result; } //HTTP请求之 post } 注: ...

February 5, 2022 · 1 min · 晚晴

安卓简单登陆界面实现

在安卓开发中登陆界面是必不可少的,好的登陆界面,会给用户更好的体验感。 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/zc" android:layout_width="310dp" android:layout_height="45dp" android:text="注册账号" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.495" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.791" /> <EditText android:id="@+id/editTextTextPassword" android:layout_width="311dp" android:layout_height="55dp" android:ems="10" android:hint="密码" android:inputType="textPassword" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/imageView2" android:layout_width="114dp" android:layout_height="108dp" android:background="@raw/login" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.186" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="登录" android:textColor="@color/purple_500" android:textSize="40dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.063" /> <EditText android:id="@+id/editTextText" android:layout_width="311dp" android:layout_height="55dp" android:ems="10" android:hint="账号" android:inputType="text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.407" /> <Button android:id="@+id/dl" android:layout_width="311dp" android:layout_height="45dp" android:text="登录" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.689" /> <TextView android:id="@+id/forget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="忘记密码?" android:textColor="#E91E63" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.146" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.564" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="50dp" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="361dp" /> </androidx.constraintlayout.widget.ConstraintLayout> 效果如下 ...

February 5, 2022 · 1 min · 晚晴

ANDROID STUDIO 之 自定义字体

在开发安卓程序时,ui的美观性尤为重要,字体也是必须要考虑的问题。 设置方法 在Android Studio中创建assets文件目录 注意在main目录下 将字体拖入到该文件中。 在Java中写入一下代码 TextView tittle; //创建一个textview对象 Typeface kaiti = Typeface.createFromAsset(getAssets(), "字体名称.ttf"); tittle = findViewById(R.id.textView); //通过iu绑定到ui tittle.setTypeface(kaiti);//设置字体

February 12, 2021 · 1 min · 晚晴

安卓 之 MD5 计算

MD5是一种神奇的算法! package cn.shilight.shiguang; import android.util.Log; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5 { public String getMd5(String source) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("md5"); byte[] bytes = source.getBytes(); byte[] targetBytes = digest.digest(bytes); char[] characters = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; StringBuilder builder = new StringBuilder(); for (byte b : targetBytes) { int high = (b >> 4) & 15; int low = b & 15; char highChar = characters[high]; char lowChar = characters[low]; builder.append(highChar).append(lowChar); } Log.i("md5",builder.toString()); return builder.toString(); } }

February 5, 2021 · 1 min · 晚晴

安卓 隐藏原生标题栏

安卓的标题 可以再对应的java文件的 setContentView()方法下加入 getSupportActionBar().hide(); Category Android Studio

February 2, 2021 · 1 min · 晚晴

安卓11 HANDLER 初试

 众所周知,安卓官放规定,IU的刷新只能在主线程上操作,而一些费时间的操作则需要放在新的线程上运行,否则就会严重的影响用户的体验,于是我们今天就使用安卓官方的api Handler 对其他线程的信息送回主线程,然后再修改UI的内容, 创建一个类继承于 Handler 重写 handleMassage 方法 class myHandler extends Handler{ public void handMassage(Massage msg){ super.handMassage(msg); //写出你要进行的UI操作} } 创建一个实例对象 private mHandler mhandler = new mHandler(); 创建一个线程 new Thread(new Runnable() { @Override public void run() { while(true){ try { Thread.sleep(1000); //加了个延迟; i++; //创建一个消息对象 Message msg = Message.obtain(); //所要发送的内容 //放在msg.what中 msg.what = i; //将信息发送给你要发送到的对象 mhandler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();

January 31, 2021 · 1 min · 晚晴