Android开发 VideoView视频播放详解
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1><p><span style="color: rgba(0, 128, 128, 1)"> <span style="color: rgba(0, 0, 0, 1)">VideoView是Android主要的视频播放View,它其实是对MediaPlayer的再次封装.如果你已经了解过MediaPlayer在使用VideoView是十分简单的.如果你想先了解<span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">MediaPlayer</span></span>可以参考我的博客:https://www.cnblogs.com/guanxinjing/p/11019662.html</span></span></p>
<p><span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">在没有复杂的要求下使用<span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">VideoView</span></span>播放视频是十分快速且方便的选择.并且不需要苦恼视频尺寸的计算(说到视频尺寸计算,个人瞎折腾出了一个计算方法.虽然也可以将视频适配的很完美,但是总的还是没有<span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">VideoView</span></span></span></span>内置的视频尺寸适配厉害,有兴趣的可以阅读一下源代码里<span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">VideoView的视频适配,这个才是精华部分...</span></span></span></span>)</span></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">实现流程</span></h1>
<ul>
<li> 获取权限</li>
<li> 保持屏幕常亮</li>
<li> xml布局里添加VideoView</li>
<li> 初始化配置<span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">VideoView</span></span></li>
<li> 播放视频</li>
<li> 暂停视频</li>
<li> 获取播放时间信息</li>
<li> 停止视频</li>
</ul>
<h1><span style="color: rgba(0, 128, 128, 1)">获取权限</span></h1>
<p> 这个是播放本地视频的demo,所以只添加了需要SD卡权限.另外VideoView是支持网络视频播放的如果你需要播放网络视频则还需要添加网络权限</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.WRITE_EXTERNAL_STORAGE"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.READ_EXTERNAL_STORAGE"</span> <span style="color: rgba(0, 0, 255, 1)">/></span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">保持屏幕常亮</span></h1>
<p>音视频开发的基本操作,在xml的根布局上添加下面这个属性</p>
<div class="cnblogs_code">
<pre>android:keepScreenOn="true"</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">xml布局里添加VideoView</span></h1>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">VideoView
</span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/video_view"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="wrap_content"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="wrap_content"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintBottom_toBottomOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">/></span></pre>
</div>
<p>基本操作,但是这里有一个你可能会忽视的VideoView的高宽配置.了解这个你可以看出VideoView自带的视频尺寸适配还是十分完美的.</p>
<p>1.第一种当你<span style="color: rgba(0, 0, 0, 1)">android:layout_width="wrap_content" 和 android:layout_height="wrap_content" 都设置为wrap_content时,这个时候View适配视频是一个在当前设备屏幕下最合适的一个比例. 虽然比例是最合适的但是View宽和高并不会一定铺满屏幕.这种方式适合在一些悬浮的小窗口播放时使用.</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">2.第二种就是满足屏幕的一边,<span style="color: rgba(0, 0, 0, 1)">满足屏幕的</span>一边的意思是让VideoView始终铺满设备屏幕的宽或者高, 这里有一个原则就是始终满足最小的那个一个边. </span></p>
<p><span style="color: rgba(0, 0, 0, 1)">我们在竖屏的情况下首先要满足宽,所以属性应该配置成 android:layout_width="match_parent" android:layout_height="wrap_content"</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">反之如果我们在横屏的情况就要满足高度.所以属性应该配置成 android:layout_width="wrap_content" android:layout_height="match_parent"</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">这样我们的视频才不会变形拉伸.<strong><span style="color: rgba(255, 0, 0, 1)">重点!</span>这种方式是我们最适用在视频播放时的使用</strong>.(如果你是动态切换横竖屏,我们也可以在代码里重新设置VideoView的layout_width</span>和<span style="color: rgba(0, 0, 0, 1)">layout_height)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">3.第三种 <span style="color: rgba(0, 0, 0, 1)">layout_width和<span style="color: rgba(0, 0, 0, 1)">layout_height</span></span>属性都是</span><span style="color: rgba(0, 0, 0, 1)">match_parent</span><span style="color: rgba(0, 0, 0, 1)">,这个将无法避免视频的变形拉伸,不建议这样配置.</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">4.第四种 <span style="color: rgba(0, 0, 0, 1)">layout_width和<span style="color: rgba(0, 0, 0, 1)">layout_height</span></span>属性都自己设置固定大小的值.<span style="color: rgba(0, 0, 0, 1)">这个也将无法避免视频的变形拉伸.如果,你还是一定需要用小窗口播放,这里可以给出一个思路:</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">就是在VideoView外面在套一个小窗口的黑色背景View,而你只要遵守第二条情况满足这小窗口的黑色背景View的最短的一边.就可以完美的适配视频了.按自动比例缩小视频,其他地方会变成电影一样的黑边效果.布局参考如下:</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">View
</span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/video_bg"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="100dp"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="50dp"</span><span style="color: rgba(255, 0, 0, 1)">
android:background</span><span style="color: rgba(0, 0, 255, 1)">="@color/fontBlack1"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintBottom_toBottomOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">VideoView
</span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/video_view2"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="wrap_content"</span><span style="color: rgba(255, 0, 0, 1)">
android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="@id/video_bg"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintBottom_toBottomOf</span><span style="color: rgba(0, 0, 255, 1)">="@id/video_bg"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="@id/video_bg"</span><span style="color: rgba(255, 0, 0, 1)">
app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="@id/video_bg"</span><span style="color: rgba(0, 0, 255, 1)">/></span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">初始化配置VideoView </span></h1>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> initVideoView(){
File file </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> File(getExternalCacheDir(),"demo.mp4"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">file.exists()){
Toast.makeText(</span><span style="color: rgba(0, 0, 255, 1)">this</span>, "视频不存在"<span style="color: rgba(0, 0, 0, 1)">, Toast.LENGTH_SHORT).show();
finish();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
mVideoView.setVideoPath(file.getAbsolutePath());</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置视频文件</span>
mVideoView.setOnPreparedListener(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MediaPlayer.OnPreparedListener() {
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onPrepared(MediaPlayer mp) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">视频加载完成,准备好播放视频的回调</span>
<span style="color: rgba(0, 0, 0, 1)">
}
});
mVideoView.setOnCompletionListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MediaPlayer.OnCompletionListener() {
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCompletion(MediaPlayer mp) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">视频播放完成后的回调</span>
<span style="color: rgba(0, 0, 0, 1)">
}
});
mVideoView.setOnErrorListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MediaPlayer.OnErrorListener() {
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> onError(MediaPlayer mp, <span style="color: rgba(0, 0, 255, 1)">int</span> what, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> extra) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">异常回调</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果方法处理了错误,则为true;否则为false。返回false或根本没有OnErrorListener,将导致调用OnCompletionListener。</span>
<span style="color: rgba(0, 0, 0, 1)"> }
});
mVideoView.setOnInfoListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MediaPlayer.OnInfoListener() {
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> onInfo(MediaPlayer mp, <span style="color: rgba(0, 0, 255, 1)">int</span> what, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> extra) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">信息回调
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> what 对应返回的值如下
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_UNKNOWN = 1;媒体信息未知
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; 媒体信息视频跟踪滞后
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; 媒体信息\视频渲染\开始
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_BUFFERING_START = 701; 媒体信息缓冲启动
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_BUFFERING_END = 702; 媒体信息缓冲结束
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_NETWORK_BANDWIDTH = 703; 媒体信息网络带宽(703)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; 媒体-信息-坏-交错
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_NOT_SEEKABLE = 801; 媒体信息找不到
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_METADATA_UPDATE = 802; 媒体信息元数据更新
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; 媒体信息不支持字幕
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; 媒体信息字幕超时</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果方法处理了信息,则为true;如果没有,则为false。返回false或根本没有OnInfoListener,将导致丢弃该信息。</span>
<span style="color: rgba(0, 0, 0, 1)"> }
});
}</span></pre>
</div>
<h3><span style="color: rgba(0, 0, 0, 1)">如果是Raw目录下的视频</span></h3>
<pre class="highlighter-hljs" data-dark-theme="true"><code>val roastedDuck = Uri.parse("android.resource://你的应用包名/" + R.raw.big_buck_bunny)
mBinding.video.setVideoURI(roastedDuck)</code></pre>
<h1><span style="color: rgba(0, 128, 128, 1)">播放视频</span></h1>
<div class="cnblogs_code">
<pre>mVideoView.start();</pre>
</div>
<p>注意,播放视频时一定要确定setOnPreparedListener返回了已经视频准备完成的回调.</p>
<h1><span style="color: rgba(0, 128, 128, 1)">暂停视频</span></h1>
<div class="cnblogs_code">
<pre>mVideoView.pause();</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">获取播放时间信息</span></h1>
<div class="cnblogs_code">
<pre>mVideoView.getDuration();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取视频的总时长</span>
mVideoView.getCurrentPosition();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取视频的当前播放位置</span></pre>
</div>
<p>这2个方法本质上还是调用MediaPlayer获取的,获取到时长后你可以配合Handler与SeekBar配合来实现自定义进度条功能.这里就不在啰嗦了.有兴趣可以参考我的一个简单的demo(虽然demo里是用MediaPlayer实现,但是原理一致):https://www.cnblogs.com/guanxinjing/p/11024195.html</p>
<h1><span style="color: rgba(0, 128, 128, 1)">停止释放</span></h1>
<div class="cnblogs_code">
<pre>mVideoView.stopPlayback();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">停止播放视频,并且释放</span>
mVideoView.suspend();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在任何状态下释放媒体播放器</span></pre>
</div>
<pre class="highlighter-hljs" data-dark-theme="true"><code>两个方法都有停止并且释放内存的作用,但是stopPlayback()看底层代码并没有重置,所以应该只是释放内存,但是没有释放配置资源(但是想不在配一次视频路径应该是需要调用mMediaPlayer.prepareAsync();方法,看不懂这个?可以参考我MediaPlayer入门的博客).
而suspend则更加彻底的释放了所有配置信息和内存.</code></pre>
<h1><span style="color: rgba(0, 128, 128, 1)">其他Api介绍</span></h1>
<ul>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.canPause(); //是否可以暂停</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.canSeekBackward(); //视频是否可以向后调整播放位置</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.canSeekForward(); //视频是否可以向前调整播放位置</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.getBufferPercentage(); //获取视频缓冲百分比</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.resolveAdjustedSize(); //获取自动解析后VideoView的大小</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.resume(); //重新开始播放</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.isPlaying(); //是否在播放中</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.setMediaController(); //设置多媒体控制器</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.onKeyDown(); //发送物理按键值</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">mVideoView.setVideoURI(); //播放网络视频,参数为网络地址</span></li>
</ul>
<h1><span style="color: rgba(22, 145, 121, 1)">播放网络视频</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">下面的例子使用了原生自带的MediaController多媒体控制器,在开发一些简单的视频,或者你实在懒得写逻辑的时候,可以直接导入这个,或者复制一份出来改成自己需要的UI</span></p>
<div>
<pre class="highlighter-hljs" data-dark-theme="true"><code>override fun onCreate(savedInstanceState: Bundle?) {
val isPortrait = intent.getBooleanExtra(IS_PORTRAIT, true)
requestedOrientation = if (isPortrait) {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT //设置屏幕为竖屏, 设置后会锁定方向
} else {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE //设置屏幕为横屏, 设置后会锁定方向
}
super.onCreate(savedInstanceState)
window.statusBarColor = Color.BLACK /*设置状态栏背景颜色为黑色*/
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
setContentView(mBinding.root)
val fileUrl = intent.getStringExtra(URL_PATH)
mBinding.videoView.setVideoURI(Uri.parse(fileUrl))
//mediaController是原生默认提供的播放器控制器,添加这个后界面上会自动显示进度条,播放时间,开始暂停等等功能
val mediaController = MediaController(this)
mediaController.setAnchorView(mBinding.videoView)
mBinding.videoView.setMediaController(mediaController)
mBinding.videoView.start()
mBinding.videoView.setOnPreparedListener { mp->
Log.e(TAG, "视频加载完成,准备好播放视频的回调")
}
mBinding.videoView.setOnCompletionListener {
Log.e(TAG, "视频播放完成")
}
}</code></pre>
</div>
<p> </p>
<p> </p>
<p>end</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<div style="text-align: center">
<p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11177739.html </p>
<div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/11177739.html
頁:
[1]