【Android】通知的使用

news2025/1/9 16:45:00

使用通知

通知(notification)是Android系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知后,手机最上方的状态栏中会显示一个通知的图标,下拉状态栏后可以看到通知的详细内容。

创建通知渠道

什么是通知渠道呢?顾名思义,就是每条通知都要属于一个对应的渠道。每个应用程序都可以自由地创建当前应用拥有哪些通知渠道,但是这些通知渠道的控制权是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动或者是否要关闭这个渠道的通知。拥有了这些控制权之后,用户就再也不用害怕那些垃圾通知的打扰了,因为用户可以自主地选择关心哪些通知、不关心哪些通知。以刚才的场景举例,微博就可以创建两种通知渠道,一个关注,一个推荐。而我作为用户,如果对推荐类的通知不感兴趣,那么我就可以直接将推荐通知渠道关闭,这样既不影响我接收关心的通知,又不会让那些我不关心的通知来打扰我了。对于每个应用来说,通知渠道的划分是非常考究的,因为通知渠道一旦创建之后就不能再修改了,因此开发者需要仔细分析自己的应用程序一共有哪些类型的通知,然后再去创建相应的通知渠道。

使用方法

1.NotificationManager对通知进行管理

首先需要一个NotificationManager对通知进行管理,可以通过调用Context的getSystemService()方法获取。getSystemService()方法接收一个字符串参数用于确定获取系统的哪个服务,这里我们传入Context.NOTIFICATION_SERVICE即可。因此,获取NotificationManager的实例就可以写成:

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

接下来要使用NotificationChannel类构建一个通知渠道,并调用NotificationManager的createNotificationChannel()方法完成创建。由于NotificationChannel类和createNotificationChannel()方法都是Android 8.0系统中新增的API,因此我们在使用的时候还需要进行版本判断才可以,写法如下:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    // 获取NotificationManager服务
    android.app.NotificationManager manager = (android.app.NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    // 定义通知渠道的ID、名称和重要性
    String channelId = "your_channel_id"; // 这里替换成您的渠道ID
    String channelName = "Your Channel Name"; // 这里替换成您的渠道名称
    int importance = android.app.NotificationManager.IMPORTANCE_DEFAULT; // 设置通知的重要性等级

    // 创建NotificationChannel对象
    android.app.NotificationChannel channel = new android.app.NotificationChannel(channelId, channelName, importance);

    // 配置NotificationChannel的属性(可选)
    channel.setDescription("Your channel description"); // 设置渠道描述

    // 注册通知渠道
    manager.createNotificationChannel(channel);
}

创建一个通知渠道至少需要渠道ID、渠道名称以及重要等级这3个参数,其中渠道ID可以随便定义,只要保证全局唯一性就可以。渠道名称是给用户看的,需要可以清楚地表达这个渠道的用途。通知的重要等级主要有IMPORTANCE_HIGH、IMPORTANCE_DEFAULT、IMPORTANCE_LOW、IMPORTANCE_MIN这几种,对应的重要程度依次从高到低。不同的重要等级会决定通知的不同行为,后面我们会通过具体的例子进行演示。当然这里只是初始状态下的重要等级,用户可以随时手动更改某个通知渠道的重要等级,开发者是无法干预的。

通知的基本用法

了解了如何创建通知渠道之后,下面我们就来看一下通知的使用方法吧。通知的用法还是比较灵活的,既可以在Activity里创建,也可以在BroadcastReceiver里创建,当然还可以在后面我们即将学习的Service里创建。相比于BroadcastReceiver和Service,在Activity里创建通知的场景还是比较少的,因为一般只有当程序进入后台的时候才需要使用通知。

2.使用一个Builder构造器来创建Notification对象(NotificationCompat)

首先需要使用一个Builder构造器来创建Notification对象,但问题在于,Android系统的每一个版本都会对通知功能进行或多或少的修改,API不稳定的问题在通知上凸显得尤其严重,比方说刚刚介绍的通知渠道功能在Android 8.0系统之前就是没有的。那么该如何解决这个问题呢?其实解决方案我们之前已经见过好几回了,就是使用AndroidX库中提供的兼容API。AndroidX库中提供了一个NotificationCompat类,使用这个类的构造器创建Notification对象,就可以保证我们的程序在所有Android系统版本上都能正常工作了,代码如下所示:

    // 使用NotificationChannel的ID创建NotificationCompat.Builder
    notification = new NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_notification) // 设置小图标
            .setContentTitle("Your Title") // 设置通知标题
            .setContentText("Your Content") // 设置通知内容
            .setChannelId(channelId) // 设置通知渠道ID
            .build();

NotificationCompat.Builder的构造函数中接收两个参数:

第一个参数是context,这个没什么好说的;

第二个参数是渠道ID,需要和我们在创建通知渠道时指定的渠道ID相匹配才行。

当然,上述代码只是创建了一个空的Notification对象,并没有什么实际作用,我们可以在最终的build()方法之前连缀任意多的设置方法来创建一个丰富的Notification对象,

  • setContentTitle()方法用于指定通知的标题内容,下拉系统状态栏就可以看到这部分内容。
  • setContentText()方法用于指定通知的正文内容,同样下拉系统状态栏就可以看到这部分内容。
  • setSmallIcon()方法用于设置通知的小图标,注意,只能使用纯alpha图层的图片进行设置,小图标会显示在系统状态栏上。
  • setLargeIcon()方法用于设置通知的大图标,当下拉系统状态栏时,就可以看到设置的大图标了。
3.NotificationManager的notify()方法

以上工作都完成之后,只需要调用NotificationManager的notify()方法就可以让通知显示出来了。

notify()方法接收两个参数:

第一个参数是id,要保证为每个通知指定的id都是不同的;

第二个参数则是Notification对象,这里直接将我们刚刚创建好的Notification对象传入即可。

因此,显示一个通知就可以写成:

manager.notify(1, notification)

新建一个NotificationTest项目,并修改activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button android:id="@+id/sendNotice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Notice" />
</LinearLayout>

布局文件非常简单,里面只有一个“Send Notice”按钮,用于发出一条通知。接下来修改MainActivity中的代码,如下所示:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
    private Button sendNotice;
    private NotificationManager manager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取系统服务中的NotificationManager
        manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // 检查Android版本是否在O(API级别26)及以上
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建一个新的通知渠道
            NotificationChannel channel = new NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT);
            // 注册通知渠道到系统中
            manager.createNotificationChannel(channel);
        }

        sendNotice = findViewById(R.id.sendNotice);
        sendNotice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Notification.Builder builder = new Notification.Builder(MainActivity.this, "normal")
                        .setContentTitle("This is content title")
                        .setContentText("This is content text")
                        .setSmallIcon(R.drawable.ic_launcher_background)
                        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground));

                Notification notification = builder.build();
                manager.notify(1, notification);
            }
        });
    }
}

在这里插入图片描述

应用程序尝试在目标SDK为Android 13(API级别33)或更高版本的设备上发送通知,但没有正确请求或检查POST_NOTIFICATIONS权限。从Android 13开始,应用必须在运行时动态请求此权限才能发送通知。

为了修复这个问题,需要确保应用在尝试发送通知之前已经获得了POST_NOTIFICATIONS权限。这通常涉及到两步:

  1. 在应用的AndroidManifest.xml文件中声明POST_NOTIFICATIONS权限。
  2. 在应用的代码中动态请求这个权限。

我们首先获取了NotificationManager的实例,并创建了一个ID为normal通知渠道。创建通知渠道的代码只在第一次执行的时候才会创建,当下次再执行创建代码时,系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响运行效率。

接下来在“Send Notice”按钮的点击事件里完成了通知的创建工作,创建的过程正如前面所描述的一样。

注意,在NotificationCompat.Builder的构造函数中传入的渠道ID也必须叫normal,如果传入了一个不存在的渠道ID,通知是无法显示出来的

这个时候就可以发送通知了

PendingIntent

如果你使用过Android手机,此时应该会下意识地认为这条通知是可以点击的。但是当你去点击它的时候,会发现没有任何效果。不对啊,每条通知被点击之后都应该有所反应呀。其实要想实现通知的点击效果,我们还需要在代码中进行相应的设置,这就涉及了一个新的概念——PendingIntent。

PendingIntent从名字上看起来就和Intent有些类似,它们确实存在不少共同点。比如它们都可以指明某一个“意图”,都可以用于启动Activity、启动Service以及发送广播等。不同的是,Intent倾向于立即执行某个动作,而PendingIntent倾向于在某个合适的时机执行某个动作。所以,也可以把PendingIntent简单地理解为延迟执行的Intent。

PendingIntent的用法同样很简单,它主要提供了几个静态方法用于获取PendingIntent的实例,可以根据需求来选择是使用getActivity()方法、getBroadcast()方法,还是getService()方法。

这几个方法所接收的参数都是相同的:

第一个参数依旧是Context,不用多做解释;

第二个参数一般用不到,传入0即可;

第三个参数是一个Intent对象,我们可以通过这个对象构建出PendingIntent的“意图”;

第四个参数用于确定PendingIntent的行为,有FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4种值可选,每种值的具体含义你可以查看文档,通常情况下这个参数传入0就可以了

对PendingIntent有了一定的了解后,我们再回过头来看一下NotificationCompat.Builder。这个构造器还可以连缀一个setContentIntent()方法,接收的参数正是一个PendingIntent对象。因此,这里就可以通过PendingIntent构建一个延迟执行的“意图”,当用户点击这条通知时就会执行相应的逻辑。

现在我们来优化一下NotificationTest项目,给刚才的通知加上点击功能,让用户点击它的时候可以启动另一个Activity

首先需要准备好另一个Activity,右击com.example.notificationtest包→New→Activity→Empty Activity,新建NotificationActivity。然后修改activity_notification.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="24sp"
        android:text="This is notification layout" />
</RelativeLayout>

这样就把NotificationActivity准备好了,下面我们修改MainActivity中的代码,给通知加入点击功能,如下所示:

sendNotice.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, noticebestart.class);
            PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, "normal")
                    .setContentTitle("This is content title")
                    .setContentText("This is content text")
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
                    .setContentIntent(pi)
                    .setAutoCancel(true);
            Notification notification = builder.build();
            manager.notify(1, notification);
        }
    });
}

可以看到,这里先是使用Intent表达出我们想要启动NotificationActivity的“意图”,然后将构建好的Intent对象传入PendingIntent的getActivity()方法里,以得到PendingIntent的实例,接着在NotificationCompat.Builder中调用setContentIntent()方法,把它作为参数传入即可。现在重新运行一下程序,并点击“Send Notice”按钮,依旧会发出一条通知。然后下拉系统状态栏,点击一下该通知,就会打开NotificationActivity的界面了

setAutoCancel()方法传入true,就表示当点击这个通知的时候,通知会自动取消。

显式地调用NotificationManager的cancel()方法将它取消。这里我们在cancel()方法中传入了1,这个1是什么意思呢?还记得在创建通知的时候给每条通知指定的id吗?当时我们给这条通知设置的id就是1。因此,如果你想取消哪条通知,在cancel()方法中传入该通知的id就行了。

通知的进阶技巧

setStyle()方法

这个方法允许我们构建出富文本的通知内容。也就是说,通知中不光可以有文字和图标,还可以包含更多的东西。setStyle()方法接收一个NotificationCompat.Style参数,这个参数就是用来构建具体的富文本信息的,如长文字、图片等。在开始使用setStyle()方法之前,我们先来做一个试验吧,之前的通知内容都比较短,如果设置成很长的文字会是什么效果呢?(会发现我们的信息被省略掉了)

如果你真的非常需要在通知当中显示一段长文字通过setStyle()方法就可以做到,具体写法如下:

.setStyle(NotificationCompat.BigTextStyle().bigText("Learn how to buildnotifications, send and sync data, and use voice actions. Get the officialAndroid IDE and developer tools to build apps for Android.")).build()

这里使用了setStyle()方法替代setContentText()方法。在setStyle()方法中,我们创建了一个NotificationCompat.BigTextStyle对象,这个对象就是用于封装长文字信息的,只要调用它的bigText()方法并将文字内容传入就可以了。

除了显示长文字之外,通知里还可以显示一张大图片,具体用法是基本相似的:

.setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources, R.drawable.big_image)))

可以看到,这里仍然是调用的setStyle()方法,这次我们在参数中创建了一个NotificationCompat.BigPictureStyle对象,这个对象就是用于设置大图片的,然后调用它的bigPicture()方法并将图片传入。这里我事先准备好了一张图片,通过BitmapFactory的decodeResource()方法将图片解析成Bitmap对象,再传入bigPicture()方法中就可以了。

重要等级

接下来,我们学习一下不同重要等级的通知渠道对通知的行为具体有什么影响。其实简单来讲,就是通知渠道的重要等级越高,发出的通知就越容易获得用户的注意。

比如高重要等级的通知渠道发出的通知可以弹出横幅、发出声音,而低重要等级的通知渠道发出的通知不仅可能会在某些情况下被隐藏,而且可能会被改变显示的顺序,将其排在更重要的通知之后。

但需要注意的是,开发者只能在创建通知渠道的时候为它指定初始的重要等级,如果用户不认可这个重要等级的话,可以随时进行修改,开发者对此无权再进行调整和变更,因为通知渠道一旦创建就不能再通过代码修改了。

既然无法修改之前创建的通知渠道,那么我们就只好再创建一个新的通知渠道来测试了。修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {

    private Button sendNotice;
    private NotificationManager manager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.your_layout); // 请替换为你的布局文件

        // 初始化按钮等组件
        sendNotice = findViewById(R.id.send_notice_button); // 请替换为实际的按钮ID
        manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        // 设置按钮的点击事件
        sendNotice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 创建Intent
                Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
                PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);

                // 检查Android版本,如果是8.0以上,则创建通知渠道
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    NotificationChannel channel2 = new NotificationChannel("important", "Important", NotificationManager.IMPORTANCE_HIGH);
                    manager.createNotificationChannel(channel2);
                }

                // 创建通知
                Notification notification = new NotificationCompat.Builder(MainActivity.this, "important")
                        .setContentTitle("Your Title") // 设置通知标题
                        .setContentText("Your Text") // 设置通知内容
                        .setSmallIcon(R.drawable.ic_notification) // 设置通知小图标
                        .setContentIntent(pi) // 设置通知点击后的行为
                        .build();

                // 发送通知
                manager.notify(1, notification); // 1是通知的ID,可以自定义
            }
        });
    }
}

在这里插入图片描述

可以看到,这次的通知不是在系统状态栏显示一个小图标了,而是弹出了一个横幅,并附带了通知的详细内容,表示这是一条非常重要的通知。不管用户现在是在玩游戏还是看电影,这条通知都会显示在最上方,以此引起用户的注意。当然,使用这类通知时一定要小心,确保你的通知内容的确是至关重要的,不然如果让用户产生排斥感的话,可能会造成适得其反的效果。

  • MMKV简介: MMKV是一种专为Android设计的键值存储方案,支持多进程访问,能够提供比SharedPreferences更快的读写速度。
  • 使用场景: MMKV适用于需要快速读写操作和跨进程数据共享的应用场景,例如用户偏好设置、应用配置等。
  • 初始化方法: 文章介绍了如何初始化MMKV,包括创建实例和配置选项,以便开发者能够根据自己的需求进行设置。
  • 数据读取原理: 通过视频教程,作者详细解释了MMKV的数据存储和读取机制,帮助开发者理解其工作原理。
  • 与其他存储方案的比较: 文章还对比了MMKV与传统的SharedPreferences以及文件存储方案,突出了MMKV在性能和多进程支持方面的优势。

MMKV是一种专为Android设计的键值存储方案,支持多进程访问,能够提供比SharedPreferences更快的读写速度。

  • 使用场景: MMKV适用于需要快速读写操作和跨进程数据共享的应用场景,例如用户偏好设置、应用配置等。
  • 初始化方法: 文章介绍了如何初始化MMKV,包括创建实例和配置选项,以便开发者能够根据自己的需求进行设置。
  • 数据读取原理: 通过视频教程,作者详细解释了MMKV的数据存储和读取机制,帮助开发者理解其工作原理。
  • 与其他存储方案的比较: 文章还对比了MMKV与传统的SharedPreferences以及文件存储方案,突出了MMKV在性能和多进程支持方面的优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1980916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三十种未授权访问漏洞复现 合集( 五 )

未授权访问漏洞介绍 未授权访问可以理解为需要安全配置或权限认证的地址、授权页面存在缺陷&#xff0c;导致其他用户可以直接访问&#xff0c;从而引发重要权限可被操作、数据库、网站目录等敏感信息泄露。---->目录遍历 目前主要存在未授权访问漏洞的有:NFS服务&a…

Modern C++ 函数发展:从函数指针到匿名函数

函数作为最小的代码单元&#xff0c;在C这个大杂烩中&#xff0c;可以跟很多特性结合&#xff0c;较为复杂&#xff0c;本文讲解C中函数是如何一步步演变的。 函数 跟C中类似&#xff0c;将一部分代码封装起来&#xff0c;方便进行复用。 #include <iostream>int add(i…

【Nuxt】404 页面 和 嵌套路由

404 页面 只需要一个动态参数组件的页面即可&#xff08;slug 也可以是其他字符串&#xff09;&#xff0c;比如&#xff1a; 此时包含三个页面组件&#xff1a;/about, /about/about-fdsfsdf, /about/fdsf/fdsfs/fsdfsfsdf/…(404) 。 具体 404 路由页面可以写成某个路径下的…

【正点原子i.MX93开发板试用连载体验】中文提示词的训练

本文首发于电子发烧友论坛&#xff1a;【正点原子i.MX93开发板试用连载体验】基于深度学习的语音本地控制 - 正点原子学习小组 - 电子技术论坛 - 广受欢迎的专业电子论坛! 好久没有更新了&#xff0c;今天再来更新一下。 我们用前面提到的录音工具录制了自己的中文语音&#…

销量激增难解奇瑞焦虑:新能源短板与加班文化引争议

尽管今年上半年奇瑞汽车以惊人的48.4%同比增长率&#xff0c;力压比亚迪、吉利等竞争对手&#xff0c;成为国内汽车销量增速最快的企业&#xff0c;但这光鲜的增长数字背后&#xff0c;却隐藏着难以忽视的焦虑与困境。 奇瑞汽车的销量飞跃&#xff0c;主要得益于燃油车市场的强…

短信平台营销:解锁市场潜力的金钥匙

在瞬息万变的营销领域&#xff0c;短信平台以其直接、高效、覆盖面广的特性&#xff0c;成为众多企业争相探索的蓝海。面对中国近9亿的手机用户群体&#xff0c;这一庞大的市场潜力无疑为企业开启了无限商机的大门。 一、塑造品牌&#xff0c;提升知名度 短信平台营销是…

ProvenCore经过形式化验证的TEE OS,最高级别的安全认证CC EAL 7

这是一个闭源的TEE OS&#xff0c;但其ATF组件已提交到upstream。 实现安全功能需要硬件的高级抽象&#xff0c;通常由操作系统 (OS) 提供。由于安全功能的正确性取决于这些高级抽象的正确性&#xff0c;因此实现这些功能的操作系统应该没有可利用的漏洞。 ProvenRun 开发了 …

JavaEE---Spring MVC(3)

11.获取session 法1> 传统方式 初始状态下session为空,那么我们就需要手动设置session 2>不传统方式 但是!!!我们发现报错了! 解决方式: 设置session之后可以发现代码的session就被查到了 12.获取header 1>传统方式 这里我们规定只返回浏览器的信息 2>不…

【CodinGame】趣味算法(教学用) CLASH OF CODE -20240804

文章目录 正文写在最后END 正文 import math import sys# Auto-generated code below aims at helping you parse # the standard input according to the problem statement.n int(input()) j 1 h 0for i in range(1, n 1):j * ih iprint(j) print(h)import sys import m…

推荐一款界面优雅、功能强大的 .NET + Vue 权限管理系统

目录 前言 项目简介 项目特点 项目预览 项目演示 1、系统登录 2、系统首页 3、系统页面 4、插件示例 5、移动端 项目地址 总结 前言 今天推荐一款用 .NET 和 Vue3 实现的开源权限管理系统。它的界面清爽干净&#xff0c;功能强大&#xff0c;还具备灵活的角色权限分配…

人工智能在病理组学领域的最新研究进展|顶刊速递·24-08-05

小罗碎碎念 本期推文主题&#xff1a;人工智能在病理组学领域的最新进展 今天的推文主要涉及三个癌种——结直肠癌、肾乳头状细胞癌、上皮性卵巢癌。既有淋巴结转移的风险预测模型&#xff0c;也有结合了测序数据的多模态病理AI模型。 重点关注一下第六篇文献&#xff0c;由西…

本地化AI语音聊天voicechat2;改进版的Whisper模型,速度快50%;多代理创建儿童图画书

✨ 1: voicechat2 voicechat2是一款使用WebSockets进行快速、本地化AI语音聊天的软件。 Voicechat2 是一个快速、完全本地化的AI语音聊天系统&#xff0c;采用WebSockets技术。它运行在高性能硬件上&#xff0c;例如7900级的AMD RDNA3显卡或4090显卡&#xff0c;可以实现低至…

最全面的Python重点知识汇总,建议收藏!

Py2 VS Py3 print成为了函数&#xff0c;python2是关键字 不再有unicode对象&#xff0c;默认str就是unicode python3除号返回浮点数 没有了long类型 xrange不存在&#xff0c;range替代了xrange 可以使用中文定义函数名变量名 高级解包 和*解包 限定关键字参数 *后的变…

【区块链+医疗健康】国家儿童医学中心互联网 + 肾脏专科联盟服务平台 | FISCO BCOS应用案例

医疗资源结构的失衡在儿科领域尤为突出&#xff0c;供需矛盾突出。由于肾脏病等疑难病的特殊性&#xff0c;加之儿童疾病诊断的 复杂性&#xff0c;其诊治过程可谓“难上加难”。一些基层儿童医院由于缺乏专业的医疗团队、特殊的辅助检查手段以及 基因测序等前沿技术的支撑&…

代码随想录算法训练营第二十四天| 455.分发饼干, 376. 摆动序列 , 53. 最大子序和

今天是贪心算法学习的第一天&#xff0c;主要的学习内容有&#xff1a;贪心算法的理论基础&#xff0c;以及如何通过局部最优解推导全局最优解。 对于贪心的理论基础&#xff0c;贪心算法并没有固定的模板和套路&#xff0c;对于贪心算法的题目其实就是一种模拟题&#xff0c;…

从常春藤精英到阶下囚:加密货币行业丑闻频发,责任在「名校情节」?

撰文&#xff1a;Muyao Shen&#xff0c;彭博社 编译&#xff1a;Yangz&#xff0c;Techub News 似乎每当加密货币行业出现丑闻时&#xff0c;涉案者大都有着常春藤联盟大学或其他名校学位。本文简单整理了加密货币行业的「脏衣篓」&#xff0c;翻出了好多名校 T 恤。 就在本周…

UE5 UC++流式请求 || Varest流式调用Coze(但一次性回复,不太推荐)

文章仅供参考。C调用的是公司后台的接口&#xff0c;博主未尝试用C调用Coze的接口&#xff0c;需要补充更多的代码。 ———— C #include "HttpModule.h" #include "HttpManager.h" #include "Http.h"DECLARE_DYNAMIC_MULTICAST_DELEGATE_O…

星座运势网源码/星座屋接口/星座配对网站PHP程序带采集

星座运势网源码/星座屋接口/星座配对网站PHP程序带采集 演示站&#xff1a; https://xz.wengu8.com/ 程序说明&#xff1a; 1、前端模板PC手机端自适应。 2、每日运势/当月/当年星座运势调用星座屋API接口&#xff0c;每天只采集一次接口&#xff0c;后保存到本地调用本地…

ThreeJs控制模型骨骼实现数字人

之前章节有讲过ThreeJs加载pmd模型和vmd动作文件&#xff0c;实现动画人物根据vmd中的动作跳舞&#xff0c;不过缺点是只能按照文件中指定动作跳舞&#xff0c;如果要让一个模型做出多种动作的话&#xff0c;就需要做很多个动作文件&#xff0c;如果动作文件很多&#xff0c;加…

算力共享:forward_to_next_shard,process_prompt推断之间的链接map_partitions_to_shards

目录 forward_to_next_shard 参数 函数逻辑 _process_prompt StandardNode get_current_shard map_partitions_to_shards forward_to_next_shard 这段代码定义了一个名为 forward_to_next_shard 的异步函数,它是设计用于在分布式模型或数据处理系统中的节点(或称为“分…