今天给大家简单的写一下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. JavaScript中随着鼠标拖拽而移动的块
  2. Swift 的变化:从 2.2 到 3.0 会带来什么
  3. vba循环通过键盘某个按键按下退出循环_默纳克3000+最新系统小键盘的使用方法...
  4. Karabiner Elements使用技巧分享,帮您简单修改使用键位
  5. linux七周四次课(3月22日)
  6. FLASH寿命测试!
  7. github 更纱黑体_更纱黑体v0.12.6
  8. Android实战简易教程-第五十六枪(模拟美团客户端进度提示框)
  9. 四舍五入函数round_如何在R中使用round()将数字四舍五入
  10. 输入一个整数,输出每个数字对应的拼音 (c++)
  11. 高等数学(第七版)同济大学 总习题十一 个人解答
  12. 如何像伟大的企业家一样写作
  13. 深入理解TCP三次握手与四次挥手过程以及抓包实验
  14. 为什么有时ping不通www baidu com但可以访问www baidu com网页
  15. R studio界面介绍及par参数详解
  16. Apt-get 如何在Ubuntu/Debian上正常工作
  17. Mac下载vscode 缓慢?以下解决方法起飞下载
  18. 【阶段总结】研一上学期总结
  19. informa医药数据库价格
  20. 北京理工大学-嵩天python语言程序设计-8-程序设计方法学

热门文章

  1. 今天,Java27岁了!
  2. 172.16.82.0/25的含义,IP段,掩码
  3. 计算机应用专业的基础知识,计算机应用专业基础知识考试大纲.doc
  4. Unity3D 优化总篇
  5. C语言输入和输出(printf和scanf函数、putchar和getchar函数)
  6. java运费模板设计,拼多多运费模板怎么设置
  7. SRE中Oncall的9条原则
  8. deepin系统使用ifconfig -a 输出参数详细介绍
  9. 微信小程序填坑之路(三)--上传头像
  10. Python——阶段性总结(一)