今天给大家简单的写一下IJkPlay视频播放的简单实现。

首先下载IjkPlay资源包:

ijkplayer导包源码下载https://github.com/lmx-fashion/IjikPlayer
我们需要的只有widget.media和libs ,直接复制到工程中就可以了

接下来就是各种配置了:

修改APP下的build.gradle, 主要设置.so及.aar的位置:

apply plugin: 'com.android.application'android {compileSdkVersion 25buildToolsVersion "24.0.3"defaultConfig {applicationId "com.bwie.test.yueijkplaytext"minSdkVersion 15targetSdkVersion 25versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}sourceSets {main {jniLibs.srcDirs = ['libs']  /**在libs文件夹下找so文件*/}}
}
repositories {mavenCentral()flatDir {dirs 'libs' /**在libs文件夹下找aar文件*/}
}dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {exclude group: 'com.android.support', module: 'support-annotations'})compile 'com.android.support:appcompat-v7:25.3.1'testCompile 'junit:junit:4.12'compile(name: 'ijkplayer-java-release', ext: 'aar') /**编译ijkplayer-java-release.aar文件*/
}

配置三处位置,arr、so文件、导入依赖

在清单文件中配置两行代码,这两行代码主要是调整视频的横竖屏配置

还有,不要忘了加网络权限!!

...
<activity android:name=".MainActivity"android:screenOrientation="sensorLandscape"android:configChanges="orientation|keyboardHidden">
...
</activity>
...
<uses-permission android:name="android.permission.INTERNET"/>

接下来就是antivity.xml文件,主要写Ijkplay的布局,切记!!要重新自己写一遍,后去自己系统的Ijkplay

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.bwie.test.yueijkplaytext.MainActivity"><widget.media.IjkVideoViewandroid:id="@+id/video_view"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout>

接下来就是MainAvtivity.java:

package com.bwie.test.yueijkplaytext;import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;import widget.media.IRenderView;
import widget.media.IjkVideoView;public class MainActivity extends AppCompatActivity {private IjkVideoView videoView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);videoView = (IjkVideoView) findViewById(R.id.video_view);videoView.setAspectRatio(IRenderView.AR_ASPECT_FIT_PARENT);videoView.setVideoURI(Uri.parse("http://mp4.vjshi.com/2013-05-28/2013052815051372.mp4"));videoView.start();}
}

这是直接从网络上下载视频,也可以直接播放本地视频:+号前面的是scard的地址,后面是咱们需要拼接的

String localPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/local"+"/adc.mp4";

好了,到这里就基本上完成了,


封装Ijkplay:

上面只是ijkplayer的一个基本用法。我们可以对ijkplayer进行一次封装,让ijkplayer使用起来更加简单

功能:

  • 使用Vitamio的VideoView进行视频播放
  • 视频左侧界面(左1/2以内)上下滑动调节亮度
  • 视频右侧界面(右1/2以外)上下滑动调节声音
  • 双击切换视频窗口布局
  • 非直播状态,可以左右滑动调节当前播放进度
public class PlayerManager {/*** 可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过view的大小超过部分裁剪处理*/public static final String SCALETYPE_FITPARENT="fitParent";/*** 可能会剪裁,等比例放大视频,直到填满View为止,超过View的部分作裁剪处理*/public static final String SCALETYPE_FILLPARENT="fillParent";/*** 将视频的内容完整居中显示,如果视频大于view,则按比例缩视频直到完全显示在view中*/public static final String SCALETYPE_WRAPCONTENT="wrapContent";/*** 不剪裁,非等比例拉伸画面填满整个View*/public static final String SCALETYPE_FITXY="fitXY";/*** 不剪裁,非等比例拉伸画面到16:9,并完全显示在View中*/public static final String SCALETYPE_16_9="16:9";/*** 不剪裁,非等比例拉伸画面到4:3,并完全显示在View中*/public static final String SCALETYPE_4_3="4:3";/*** 状态常量*/private final int STATUS_ERROR=-1;private final int STATUS_IDLE=0;private final int STATUS_LOADING=1;private final int STATUS_PLAYING=2;private final int STATUS_PAUSE=3;private final int STATUS_COMPLETED=4;private final Activity activity;private final IjkVideoView videoView;private final AudioManager audioManager;public GestureDetector gestureDetector;private boolean playerSupport;private boolean isLive = false;//是否为直播private boolean fullScreenOnly;private boolean portrait;private final int mMaxVolume;private int screenWidthPixels;private int currentPosition;private int status=STATUS_IDLE;private long pauseTime;private String url;private float brightness=-1;private int volume=-1;private long newPosition = -1;private long defaultRetryTime=5000;private OrientationEventListener orientationEventListener;private PlayerStateListener playerStateListener;public void setPlayerStateListener(PlayerStateListener playerStateListener) {this.playerStateListener = playerStateListener;}private OnErrorListener onErrorListener=new OnErrorListener() {@Overridepublic void onError(int what, int extra) {}};private OnCompleteListener onCompleteListener=new OnCompleteListener() {@Overridepublic void onComplete() {}};private OnInfoListener onInfoListener=new OnInfoListener(){@Overridepublic void onInfo(int what, int extra) {}};private OnControlPanelVisibilityChangeListener onControlPanelVisibilityChangeListener=new OnControlPanelVisibilityChangeListener() {@Overridepublic void change(boolean isShowing) {}};/*** try to play when error(only for live video)* @param defaultRetryTime millisecond,0 will stop retry,default is 5000 millisecond*/public void setDefaultRetryTime(long defaultRetryTime) {this.defaultRetryTime = defaultRetryTime;}public PlayerManager(final Activity activity) {try {IjkMediaPlayer.loadLibrariesOnce(null);IjkMediaPlayer.native_profileBegin("libijkplayer.so");playerSupport=true;} catch (Throwable e) {Log.e("GiraffePlayer", "loadLibraries error", e);}this.activity=activity;screenWidthPixels = activity.getResources().getDisplayMetrics().widthPixels;videoView = (IjkVideoView) activity.findViewById(R.id.video_view);videoView.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(IMediaPlayer mp) {statusChange(STATUS_COMPLETED);onCompleteListener.onComplete();}});videoView.setOnErrorListener(new IMediaPlayer.OnErrorListener() {@Overridepublic boolean onError(IMediaPlayer mp, int what, int extra) {statusChange(STATUS_ERROR);onErrorListener.onError(what,extra);return true;}});videoView.setOnInfoListener(new IMediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(IMediaPlayer mp, int what, int extra) {switch (what) {case IMediaPlayer.MEDIA_INFO_BUFFERING_START:statusChange(STATUS_LOADING);break;case IMediaPlayer.MEDIA_INFO_BUFFERING_END:statusChange(STATUS_PLAYING);break;case IMediaPlayer.MEDIA_INFO_NETWORK_BANDWIDTH://显示下载速度
//                      Toast.show("download rate:" + extra);break;case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:statusChange(STATUS_PLAYING);break;}onInfoListener.onInfo(what,extra);return false;}});audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);mMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);gestureDetector = new GestureDetector(activity, new PlayerGestureListener());if (fullScreenOnly) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}portrait=getScreenOrientation()== ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;if (!playerSupport) {DebugLog.e("播放器不支持此设备");}}private void statusChange(int newStatus) {status = newStatus;if (!isLive && newStatus==STATUS_COMPLETED) {DebugLog.d("statusChange STATUS_COMPLETED...");if (playerStateListener != null){playerStateListener.onComplete();}}else if (newStatus == STATUS_ERROR) {DebugLog.d("statusChange STATUS_ERROR...");if (playerStateListener != null){playerStateListener.onError();}} else if(newStatus==STATUS_LOADING){
//            $.id(R.id.app_video_loading).visible();if (playerStateListener != null){playerStateListener.onLoading();}DebugLog.d("statusChange STATUS_LOADING...");} else if (newStatus == STATUS_PLAYING) {DebugLog.d("statusChange STATUS_PLAYING...");if (playerStateListener != null){playerStateListener.onPlay();}}}public void onPause() {pauseTime= System.currentTimeMillis();if (status==STATUS_PLAYING) {videoView.pause();if (!isLive) {currentPosition = videoView.getCurrentPosition();}}}public void onResume() {pauseTime=0;if (status==STATUS_PLAYING) {if (isLive) {videoView.seekTo(0);} else {if (currentPosition>0) {videoView.seekTo(currentPosition);}}videoView.start();}}public void onDestroy() {orientationEventListener.disable();videoView.stopPlayback();}public void play(String url) {this.url = url;if (playerSupport) {videoView.setVideoPath(url);videoView.start();}}private String generateTime(long time) {int totalSeconds = (int) (time / 1000);int seconds = totalSeconds % 60;int minutes = (totalSeconds / 60) % 60;int hours = totalSeconds / 3600;return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds);}private int getScreenOrientation() {int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();DisplayMetrics dm = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(dm);int width = dm.widthPixels;int height = dm.heightPixels;int orientation;// if the device's natural orientation is portrait:if ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && height > width ||(rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && width > height) {switch (rotation) {case Surface.ROTATION_0:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;case Surface.ROTATION_90:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;case Surface.ROTATION_180:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;break;case Surface.ROTATION_270:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;break;default:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;}}// if the device's natural orientation is landscape or if the device// is square:else {switch (rotation) {case Surface.ROTATION_0:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;case Surface.ROTATION_90:orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;break;case Surface.ROTATION_180:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;break;case Surface.ROTATION_270:orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;break;default:orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;break;}}return orientation;}/*** 滑动改变声音大小** @param percent*/private void onVolumeSlide(float percent) {if (volume == -1) {volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);if (volume < 0)volume = 0;}int index = (int) (percent * mMaxVolume) + volume;if (index > mMaxVolume) {index = mMaxVolume;} else if (index < 0){index = 0;}// 变更声音audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);// 变更进度条int i = (int) (index * 1.0 / mMaxVolume * 100);String s = i + "%";if (i == 0) {s = "off";}DebugLog.d("onVolumeSlide:"+s);}private void onProgressSlide(float percent) {long position = videoView.getCurrentPosition();long duration = videoView.getDuration();long deltaMax = Math.min(100 * 1000, duration - position);long delta = (long) (deltaMax * percent);newPosition = delta + position;if (newPosition > duration) {newPosition = duration;} else if (newPosition <= 0) {newPosition=0;delta=-position;}int showDelta = (int) delta / 1000;if (showDelta != 0) {String text = showDelta > 0 ? ("+" + showDelta) : "" + showDelta;DebugLog.d("onProgressSlide:" + text);}}/*** 滑动改变亮度** @param percent*/private void onBrightnessSlide(float percent) {if (brightness < 0) {brightness = activity.getWindow().getAttributes().screenBrightness;if (brightness <= 0.00f){brightness = 0.50f;}else if (brightness < 0.01f){brightness = 0.01f;}}DebugLog.d("brightness:"+brightness+",percent:"+ percent);WindowManager.LayoutParams lpa = activity.getWindow().getAttributes();lpa.screenBrightness = brightness + percent;if (lpa.screenBrightness > 1.0f){lpa.screenBrightness = 1.0f;}else if (lpa.screenBrightness < 0.01f){lpa.screenBrightness = 0.01f;}activity.getWindow().setAttributes(lpa);}public void setFullScreenOnly(boolean fullScreenOnly) {this.fullScreenOnly = fullScreenOnly;tryFullScreen(fullScreenOnly);if (fullScreenOnly) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);} else {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);}}private void tryFullScreen(boolean fullScreen) {if (activity instanceof AppCompatActivity) {ActionBar supportActionBar = ((AppCompatActivity) activity).getSupportActionBar();if (supportActionBar != null) {if (fullScreen) {supportActionBar.hide();} else {supportActionBar.show();}}}setFullScreen(fullScreen);}private void setFullScreen(boolean fullScreen) {if (activity != null) {WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();if (fullScreen) {attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;activity.getWindow().setAttributes(attrs);activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);} else {attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);activity.getWindow().setAttributes(attrs);activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);}}}/*** <pre>*     fitParent:可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过view的大小超过部分裁剪处理*     fillParent:可能会剪裁,等比例放大视频,直到填满View为止,超过View的部分作裁剪处理*     wrapContent:将视频的内容完整居中显示,如果视频大于view,则按比例缩视频直到完全显示在view中*     fitXY:不剪裁,非等比例拉伸画面填满整个View*     16:9:不剪裁,非等比例拉伸画面到16:9,并完全显示在View中*     4:3:不剪裁,非等比例拉伸画面到4:3,并完全显示在View中* </pre>* @param scaleType*/public void setScaleType(String scaleType) {if (SCALETYPE_FITPARENT.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_ASPECT_FIT_PARENT);}else if (SCALETYPE_FILLPARENT.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_ASPECT_FILL_PARENT);}else if (SCALETYPE_WRAPCONTENT.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_ASPECT_WRAP_CONTENT);}else if (SCALETYPE_FITXY.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_MATCH_PARENT);}else if (SCALETYPE_16_9.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_16_9_FIT_PARENT);}else if (SCALETYPE_4_3.equals(scaleType)) {videoView.setAspectRatio(IRenderView.AR_4_3_FIT_PARENT);}}public void start() {videoView.start();}public void pause() {videoView.pause();}public boolean onBackPressed() {if (!fullScreenOnly && getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);return true;}return false;}class Query {private final Activity activity;private View view;public Query(Activity activity) {this.activity=activity;}public Query id(int id) {view = activity.findViewById(id);return this;}public Query image(int resId) {if (view instanceof ImageView) {((ImageView) view).setImageResource(resId);}return this;}public Query visible() {if (view != null) {view.setVisibility(View.VISIBLE);}return this;}public Query gone() {if (view != null) {view.setVisibility(View.GONE);}return this;}public Query invisible() {if (view != null) {view.setVisibility(View.INVISIBLE);}return this;}public Query clicked(View.OnClickListener handler) {if (view != null) {view.setOnClickListener(handler);}return this;}public Query text(CharSequence text) {if (view!=null && view instanceof TextView) {((TextView) view).setText(text);}return this;}public Query visibility(int visible) {if (view != null) {view.setVisibility(visible);}return this;}private void size(boolean width, int n, boolean dip){if(view != null){ViewGroup.LayoutParams lp = view.getLayoutParams();if(n > 0 && dip){n = dip2pixel(activity, n);}if(width){lp.width = n;}else{lp.height = n;}view.setLayoutParams(lp);}}public void height(int height, boolean dip) {size(false,height,dip);}public int dip2pixel(Context context, float n){int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources().getDisplayMetrics());return value;}public float pixel2dip(Context context, float n){Resources resources = context.getResources();DisplayMetrics metrics = resources.getDisplayMetrics();float dp = n / (metrics.densityDpi / 160f);return dp;}}public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener {private boolean firstTouch;private boolean volumeControl;private boolean toSeek;/*** 双击*/@Overridepublic boolean onDoubleTap(MotionEvent e) {videoView.toggleAspectRatio();return true;}@Overridepublic boolean onDown(MotionEvent e) {firstTouch = true;return super.onDown(e);}/*** 滑动*/@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {float mOldX = e1.getX(), mOldY = e1.getY();float deltaY = mOldY - e2.getY();float deltaX = mOldX - e2.getX();if (firstTouch) {toSeek = Math.abs(distanceX) >= Math.abs(distanceY);volumeControl=mOldX > screenWidthPixels * 0.5f;firstTouch = false;}if (toSeek) {if (!isLive) {onProgressSlide(-deltaX / videoView.getWidth());}} else {float percent = deltaY / videoView.getHeight();if (volumeControl) {onVolumeSlide(percent);} else {onBrightnessSlide(percent);}}return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onSingleTapUp(MotionEvent e) {return true;}}/*** is player support this device* @return*/public boolean isPlayerSupport() {return playerSupport;}/*** 是否正在播放* @return*/public boolean isPlaying() {return videoView!=null?videoView.isPlaying():false;}public void stop(){videoView.stopPlayback();}public int getCurrentPosition(){return videoView.getCurrentPosition();}/*** get video duration* @return*/public int getDuration(){return videoView.getDuration();}public PlayerManager playInFullScreen(boolean fullScreen){if (fullScreen) {activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}return this;}public PlayerManager onError(OnErrorListener onErrorListener) {this.onErrorListener = onErrorListener;return this;}public PlayerManager onComplete(OnCompleteListener onCompleteListener) {this.onCompleteListener = onCompleteListener;return this;}public PlayerManager onInfo(OnInfoListener onInfoListener) {this.onInfoListener = onInfoListener;return this;}public PlayerManager onControlPanelVisibilityChange(OnControlPanelVisibilityChangeListener listener){this.onControlPanelVisibilityChangeListener = listener;return this;}/*** set is live (can't seek forward)* @param isLive* @return*/public PlayerManager live(boolean isLive) {this.isLive = isLive;return this;}public PlayerManager toggleAspectRatio(){if (videoView != null) {videoView.toggleAspectRatio();}return this;}public interface PlayerStateListener{void onComplete();void onError();void onLoading();void onPlay();}public interface OnErrorListener{void onError(int what, int extra);}public interface OnCompleteListener{void onComplete();}public interface OnControlPanelVisibilityChangeListener{void change(boolean isShowing);}public interface OnInfoListener{void onInfo(int what, int extra);}
}

封装之后的视频播放:

public class MainActivity extends AppCompatActivity implements PlayerManager.PlayerStateListener{private String url1 = "rtmp://203.207.99.19:1935/live/CCTV5";private String url2 = "http://zv.3gv.ifeng.com/live/zhongwen800k.m3u8";private String url3 = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov";private String url4 = "http://42.96.249.166/live/24035.m3u8";private PlayerManager player;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initPlayer();}private void initPlayer() {player = new PlayerManager(this);player.setFullScreenOnly(true);player.setScaleType(PlayerManager.SCALETYPE_FILLPARENT);player.playInFullScreen(true);player.setPlayerStateListener(this);player.play(url1);}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (player.gestureDetector.onTouchEvent(event))return true;return super.onTouchEvent(event);}@Overridepublic void onComplete() {}@Overridepublic void onError() {}@Overridepublic void onLoading() {}@Overridepublic void onPlay() {}
}

好了,希望能给客官们带来帮助。

谢谢~~~~

Ijkplay视频播放简单快速集成相关推荐

  1. Android PDF阅读框架/Android PDF框架简单使用,简单快速集成简易的PDF阅读器 ,AndroidPdfViewer框架简单使用。

    文章目录 1:前言 使用步骤 步骤1 导包 / 导引用 / 添加依赖 步骤2 更改xml布局文件 步骤3 java文件处理 1:前言 因为前段时间项目展示,我们小组本打算做的是TXT阅读框架,但是找了 ...

  2. Android 友盟简单快速集成

    1,打开友盟官网,进行注册,添加 app ,记住 key. 2,集成,一共两种方式,使用 jar 包和 自动集成,这里我们选择自动集成,如下: ​ 在项目的 gradle 中添加如下: reposit ...

  3. 快速集成iOS基于RTMP的视频推流

    http://www.jianshu.com/p/8ea016b2720e 效果图 iTools有点卡, 但是推到服务器倒是很快的. 推流 前言 这篇blog是iOS视频直播初窥:<喵播APP& ...

  4. Android VLC音频视频播发器快速集成教程与模块

    前言 通过该文,你能很简单的知道怎么使用vlc,并且通过封装好的方法,很简单的几句代码就能实现音频视频本地与在线播放. 转载请务必注明出处:http://blog.csdn.net/u01461403 ...

  5. GMaps.js:让你快速集成 Google Maps 服务的 jQuery 插件

    GMaps.js 功能 除了添加指定经纬度的标准地图之外,GMaps.js 还能定义地图放大的级别,添加标注,获取当前用户的地理位置(HTML5 geolocation),定义路线,绘制折线,并且实现 ...

  6. Spring Boot 快速集成第三方登录功能

    Spring Boot 快速集成第三方登录功能 前言 此 demo 主要演示 Spring Boot 项目如何使用 史上最全的第三方登录工具 - JustAuth 实现第三方登录,包括 QQ 登录.G ...

  7. 分分钟实现底部导航栏:BottomNavigationBar快速集成

    分分钟实现底部导航栏:BottomNavigationBar快速集成 github地址(完整Demo下载) github.com/Ashok-Varma- 一.简介 导航栏布局基本很多app都会用到, ...

  8. 两步实现在C代码中快速集成gtest进行单元测试

    我平时的技术支持工作主要是快速阅读和调试代码,没有太多的代测试和验证需求,所以对单元测试一直没有留意. 直到我开始从头写一些密码学的基本功能代码,例如各种哈希算法,分组密码算法,流密码算法,分组密码的 ...

  9. SpringBoot 快速集成 JWT 实现用户登录认证

    前言:当今前后端分离时代,基于Token的会话保持机制比传统的Session/Cookie机制更加方便,下面我会介绍SpringBoot快速集成JWT库java-jwt以完成用户登录认证. 一.JWT ...

最新文章

  1. python 排序算法 简书_Python---简析八大排序算法
  2. 天津商业大学计算机科学与技术分数线,天津商业大学录取分数线2021是多少分(附历年录取分数线)...
  3. linux安装oracle常见错误 总结
  4. golang使用gdb
  5. Scanner类的基本总结
  6. java项目没有bin_WebAPI项目似乎没有将转换后的web.config发布到bin文件夹?
  7. 卷王李富贵算法每日一题--分治算法(三)--逃亡
  8. python报错ValueError: invalid literal for int() with base 10解决方法
  9. PHP之常用设计模式
  10. java模板变量_IntelliJ IDEA实时模板变量
  11. 在Windows下启动java服务
  12. 开发自己的工作流(一)
  13. 计算机专业建设会议纪要,本学期第六次专业建设工作会议纪要
  14. python100内的质数_python输出100以内的质数与合数
  15. c语言中位运算符及用法
  16. uniapp中隐藏Android虚拟按键
  17. Unreal Engine 4 Radiant UI 入门教程(一)制作Radiant HUD
  18. 淘宝触屏版宝贝详情改造(一)
  19. mmsegmentation自定义新数据集
  20. 【飞桨/百度领航团/零基础Python】学习心得

热门文章

  1. 牛客小白月赛 G 异或 找规律
  2. iapp启动图代码_关于计算设备运行时间SCL代码的测试与说明
  3. 奥迪a3android auto错误,抢先体验: 奥迪A3的Android Auto车载系统
  4. Cesium:Indexed 3D Scene Layers (I3S)加载
  5. LoRa Server 配置与管理
  6. UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 34: illegal multibyte sequence
  7. iOS_SDWebImage框架分析
  8. 鼻纹、静脉、虹膜……奇奇怪怪的生物识别技术有哪些?
  9. Type-c快充协议介绍-QC和PD协议(一)
  10. 学Python可少不了项目练手,这8个小项目有趣又实用,小白也能做出来