├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── libs │ └── libvlc.aar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── info │ │ └── ruibu │ │ └── vlcandroiddemo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── info │ │ │ └── ruibu │ │ │ ├── util │ │ │ ├── LibVLCUtil.java │ │ │ └── SystemUtil.java │ │ │ └── vlcandroiddemo │ │ │ ├── MainActivity.java │ │ │ └── VLCPlayerActivity.java │ └── res │ │ ├── drawable │ │ ├── common_button.xml │ │ ├── player_button.xml │ │ ├── videoviews_seekbar_thumb.xml │ │ ├── videoviewx_pause.xml │ │ ├── videoviewx_play.xml │ │ └── videoviewx_seekbar.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── activity_vlc_player.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── pause_normal.png │ │ ├── pause_pressed.png │ │ ├── play_normal.png │ │ ├── play_pressed.png │ │ ├── seekbar_thumb_normal.png │ │ └── seekbar_thumb_pressed.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── info │ └── ruibu │ └── vlcandroiddemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | /.idea/gradle.xml 7 | .DS_Store 8 | /build 9 | /captures -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | VLCAndroidDemo -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 'android-N' 5 | buildToolsVersion "24.0.0 rc3" 6 | 7 | defaultConfig { 8 | applicationId "info.ruibu.vlcandroiddemo" 9 | minSdkVersion 16 10 | targetSdkVersion 'N' 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_7 22 | targetCompatibility JavaVersion.VERSION_1_7 23 | } 24 | repositories { 25 | flatDir { 26 | dirs 'libs' 27 | } 28 | } 29 | } 30 | 31 | dependencies { 32 | compile fileTree(dir: 'libs', include: ['*.jar']) 33 | compile(name: 'libvlc', ext: 'aar') 34 | testCompile 'junit:junit:4.12' 35 | compile 'com.android.support:support-v4:24.0.0-alpha2' 36 | compile 'com.android.support:appcompat-v7:24.0.0-alpha2' 37 | compile 'com.android.support:design:24.0.0-alpha2' 38 | compile 'com.android.support:recyclerview-v7:24.0.0-alpha2' 39 | compile 'com.android.support:cardview-v7:24.0.0-alpha2' 40 | } -------------------------------------------------------------------------------- /app/libs/libvlc.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymbrooks/VLCAndroidDemo/8e934df37cf46a0d4e36ba55f1f173739a8351a7/app/libs/libvlc.aar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Developer\OS\Android\android-sdk-windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/info/ruibu/vlcandroiddemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package info.ruibu.vlcandroiddemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/info/ruibu/util/LibVLCUtil.java: -------------------------------------------------------------------------------- 1 | package info.ruibu.util; 2 | 3 | import org.videolan.libvlc.LibVLC; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by Brooks on 2015-12-31. 9 | * LibVLCUtil LibVLC 单例 10 | */ 11 | public class LibVLCUtil { 12 | private static LibVLC libVLC = null; 13 | 14 | public synchronized static LibVLC getLibVLC(ArrayList options) throws IllegalStateException { 15 | if (libVLC == null) { 16 | if (options == null) { 17 | libVLC = new LibVLC(); 18 | } else { 19 | libVLC = new LibVLC(options); 20 | } 21 | } 22 | return libVLC; 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/info/ruibu/util/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package info.ruibu.util; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.ContentUris; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.os.Build; 9 | import android.os.Environment; 10 | import android.provider.DocumentsContract; 11 | import android.provider.MediaStore; 12 | 13 | /** 14 | * Created by Brooks on 2016-04-17. 15 | * 系统工具类 16 | */ 17 | public class SystemUtil { 18 | /** 19 | * 获取媒体文件播放时间,格式化输出 20 | * 21 | * @param ms 毫秒 22 | * @return 格式化后的结果:hh:mm:ss 23 | */ 24 | public static String getMediaTime(int ms) { 25 | int hour, mintue, second; 26 | 27 | //计算小时 1 h = 3600000 ms 28 | hour = ms / 3600000; 29 | 30 | //计算分钟 1 min = 60000 ms 31 | mintue = (ms - hour * 3600000) / 60000; 32 | 33 | //计算秒钟 1 s = 1000 ms 34 | second = (ms - hour * 3600000 - mintue * 60000) / 1000; 35 | 36 | //格式化输出,补零操作 37 | String sHour, sMintue, sSecond; 38 | if (hour < 10) { 39 | sHour = "0" + String.valueOf(hour); 40 | } else { 41 | sHour = String.valueOf(hour); 42 | } 43 | 44 | if (mintue < 10) { 45 | sMintue = "0" + String.valueOf(mintue); 46 | } else { 47 | sMintue = String.valueOf(mintue); 48 | } 49 | 50 | if (second < 10) { 51 | sSecond = "0" + String.valueOf(second); 52 | } else { 53 | sSecond = String.valueOf(second); 54 | } 55 | 56 | return sHour + ":" + sMintue + ":" + sSecond; 57 | } 58 | 59 | /** 60 | *
功能简述:4.4及以上获取图片的方法 61 | *
功能详细描述: 62 | *
注意: 63 | * 64 | * @param context 上下文 65 | * @param uri 待解析的 Uri 66 | * @return 真实路径 67 | */ 68 | @TargetApi(Build.VERSION_CODES.KITKAT) 69 | public static String getPath(final Context context, final Uri uri) { 70 | final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 71 | 72 | // DocumentProvider 73 | if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { 74 | // ExternalStorageProvider 75 | if (isExternalStorageDocument(uri)) { 76 | final String docId = DocumentsContract.getDocumentId(uri); 77 | final String[] split = docId.split(":"); 78 | final String type = split[0]; 79 | 80 | if ("primary".equalsIgnoreCase(type)) { 81 | return Environment.getExternalStorageDirectory() + "/" + split[1]; 82 | } 83 | } 84 | // DownloadsProvider 85 | else if (isDownloadsDocument(uri)) { 86 | final String id = DocumentsContract.getDocumentId(uri); 87 | final Uri contentUri = ContentUris.withAppendedId( 88 | Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 89 | 90 | return getDataColumn(context, contentUri, null, null); 91 | } 92 | // MediaProvider 93 | else if (isMediaDocument(uri)) { 94 | final String docId = DocumentsContract.getDocumentId(uri); 95 | final String[] split = docId.split(":"); 96 | final String type = split[0]; 97 | 98 | Uri contentUri = null; 99 | if ("image".equals(type)) { 100 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 101 | } else if ("video".equals(type)) { 102 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 103 | } else if ("audio".equals(type)) { 104 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 105 | } 106 | 107 | final String selection = "_id=?"; 108 | final String[] selectionArgs = new String[]{split[1]}; 109 | 110 | return getDataColumn(context, contentUri, selection, selectionArgs); 111 | } 112 | } 113 | // MediaStore (and general) 114 | else if ("content".equalsIgnoreCase(uri.getScheme())) { 115 | 116 | // Return the remote address 117 | if (isGooglePhotosUri(uri)) 118 | return uri.getLastPathSegment(); 119 | 120 | return getDataColumn(context, uri, null, null); 121 | } 122 | // File 123 | else if ("file".equalsIgnoreCase(uri.getScheme())) { 124 | return uri.getPath(); 125 | } 126 | 127 | return null; 128 | } 129 | 130 | public static String getDataColumn(Context context, Uri uri, String selection, 131 | String[] selectionArgs) { 132 | 133 | Cursor cursor = null; 134 | final String column = "_data"; 135 | final String[] projection = {column}; 136 | 137 | try { 138 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, 139 | null); 140 | if (cursor != null && cursor.moveToFirst()) { 141 | final int index = cursor.getColumnIndexOrThrow(column); 142 | return cursor.getString(index); 143 | } 144 | } finally { 145 | if (cursor != null) 146 | cursor.close(); 147 | } 148 | return null; 149 | } 150 | 151 | /** 152 | * @param uri The Uri to check. 153 | * @return Whether the Uri authority is ExternalStorageProvider. 154 | */ 155 | public static boolean isExternalStorageDocument(Uri uri) { 156 | return "com.android.externalstorage.documents".equals(uri.getAuthority()); 157 | } 158 | 159 | /** 160 | * @param uri The Uri to check. 161 | * @return Whether the Uri authority is DownloadsProvider. 162 | */ 163 | public static boolean isDownloadsDocument(Uri uri) { 164 | return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 165 | } 166 | 167 | /** 168 | * @param uri The Uri to check. 169 | * @return Whether the Uri authority is MediaProvider. 170 | */ 171 | public static boolean isMediaDocument(Uri uri) { 172 | return "com.android.providers.media.documents".equals(uri.getAuthority()); 173 | } 174 | 175 | /** 176 | * @param uri The Uri to check. 177 | * @return Whether the Uri authority is Google Photos. 178 | */ 179 | public static boolean isGooglePhotosUri(Uri uri) { 180 | return "com.google.android.apps.photos.content".equals(uri.getAuthority()); 181 | } 182 | } -------------------------------------------------------------------------------- /app/src/main/java/info/ruibu/vlcandroiddemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package info.ruibu.vlcandroiddemo; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.support.annotation.NonNull; 7 | import android.support.design.widget.TextInputLayout; 8 | import android.support.v4.app.ActivityCompat; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.os.Bundle; 12 | import android.util.Log; 13 | import android.view.View; 14 | import android.widget.Button; 15 | import android.widget.EditText; 16 | import android.widget.Toast; 17 | 18 | import info.ruibu.util.SystemUtil; 19 | 20 | public class MainActivity extends AppCompatActivity { 21 | private TextInputLayout tilRemoteVideo; 22 | private EditText etRemoteVideo; 23 | 24 | private final static int PERMISSIONS_REQUEST = 0; 25 | private final static int VIDEO_REQUEST = 1; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_main); 31 | 32 | Button btnLocalVideo = (Button) findViewById(R.id.btnLocalVideo); 33 | btnLocalVideo.setOnClickListener(new View.OnClickListener() { 34 | @Override 35 | public void onClick(View view) { 36 | if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { 37 | Toast.makeText(MainActivity.this, "播放本地视频需要读取SD卡,请允许操作SD卡的权限。", Toast.LENGTH_SHORT).show(); 38 | } 39 | 40 | if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 41 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 42 | intent.setType("*/*"); 43 | startActivityForResult(intent, VIDEO_REQUEST); 44 | } else { 45 | //请求权限 46 | ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST); 47 | } 48 | } 49 | }); 50 | 51 | tilRemoteVideo = (TextInputLayout) findViewById(R.id.tilRemoteVideo); 52 | 53 | etRemoteVideo = (EditText) findViewById(R.id.etRemoteVideo); 54 | 55 | Button btnRemoteVideo = (Button) findViewById(R.id.btnRemoteVideo); 56 | btnRemoteVideo.setOnClickListener(new View.OnClickListener() { 57 | @Override 58 | public void onClick(View view) { 59 | if (etRemoteVideo.getText().toString().equals("")) { 60 | tilRemoteVideo.setError("远程视频地址不能为空!"); 61 | return; 62 | } 63 | 64 | Intent intent = new Intent(); 65 | intent.setClass(MainActivity.this, VLCPlayerActivity.class); 66 | intent.putExtra("VideoType", "Remote"); 67 | intent.putExtra("VideoUrl", etRemoteVideo.getText().toString()); 68 | startActivity(intent); 69 | } 70 | }); 71 | } 72 | 73 | @Override 74 | public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { 75 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 76 | 77 | switch (requestCode) { 78 | case PERMISSIONS_REQUEST: { 79 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 80 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 81 | intent.setType("*/*"); 82 | startActivityForResult(intent, VIDEO_REQUEST); 83 | } 84 | } 85 | } 86 | } 87 | 88 | @Override 89 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 90 | try { 91 | super.onActivityResult(requestCode, resultCode, data); 92 | 93 | if (requestCode == VIDEO_REQUEST && data != null) { 94 | Intent intent = new Intent(); 95 | intent.setClass(MainActivity.this, VLCPlayerActivity.class); 96 | intent.putExtra("VideoType", "Local"); 97 | intent.putExtra("VideoUrl", SystemUtil.getPath(MainActivity.this, data.getData())); 98 | startActivity(intent); 99 | } 100 | } catch (Exception e) { 101 | Log.d("Local", e.toString()); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /app/src/main/java/info/ruibu/vlcandroiddemo/VLCPlayerActivity.java: -------------------------------------------------------------------------------- 1 | package info.ruibu.vlcandroiddemo; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Point; 6 | import android.net.Uri; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.view.Display; 11 | import android.view.SurfaceHolder; 12 | import android.view.SurfaceView; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.view.WindowManager; 16 | import android.widget.ImageView; 17 | import android.widget.RelativeLayout; 18 | import android.widget.SeekBar; 19 | import android.widget.TextView; 20 | 21 | import org.videolan.libvlc.IVLCVout; 22 | import org.videolan.libvlc.LibVLC; 23 | import org.videolan.libvlc.Media; 24 | import org.videolan.libvlc.MediaPlayer; 25 | 26 | import info.ruibu.util.LibVLCUtil; 27 | import info.ruibu.util.SystemUtil; 28 | 29 | public class VLCPlayerActivity extends AppCompatActivity { 30 | private IVLCVout vlcVout; 31 | private MediaPlayer mediaPlayer; 32 | 33 | private SurfaceView surfaceView; 34 | private RelativeLayout rlHub; 35 | private SeekBar seekBarTime; 36 | private TextView tvCurrentTime; 37 | private TextView tvTotalTime; 38 | private ImageView imgPlay; 39 | private SeekBar seekBarVolume; 40 | private TextView tvFullScreen; 41 | private boolean isFullScreen = false; 42 | private long totalTime = 0; 43 | 44 | private SeekBar.OnSeekBarChangeListener onTimeSeekBarChangeListener; 45 | private SeekBar.OnSeekBarChangeListener onVolumeSeekBarChangeListener; 46 | private IVLCVout.Callback callback; 47 | private MediaPlayer.EventListener eventListener; 48 | 49 | private int videoWidth; 50 | private int videoHight; 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | try { 55 | super.onCreate(savedInstanceState); 56 | setContentView(R.layout.activity_vlc_player); 57 | 58 | Intent intent = getIntent(); 59 | if (intent == null) { 60 | return; 61 | } 62 | 63 | RelativeLayout rlPlayer = (RelativeLayout) findViewById(R.id.rlPlayer); 64 | rlPlayer.setOnClickListener(new View.OnClickListener() { 65 | @Override 66 | public void onClick(View v) { 67 | if (isFullScreen) { 68 | rlHub.setVisibility(View.VISIBLE); 69 | } 70 | } 71 | }); 72 | 73 | surfaceView = (SurfaceView) findViewById(R.id.surfaceView); 74 | SurfaceHolder surfaceHolder = surfaceView.getHolder(); 75 | rlHub = (RelativeLayout) findViewById(R.id.rlHub); 76 | seekBarTime = (SeekBar) findViewById(R.id.seekBarTime); 77 | onTimeSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { 78 | @Override 79 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 80 | try { 81 | if (!mediaPlayer.isSeekable() || totalTime == 0) { 82 | return; 83 | } 84 | 85 | if (progress > totalTime) { 86 | progress = (int) totalTime; 87 | } 88 | 89 | if (fromUser) { 90 | mediaPlayer.setTime((long) progress); 91 | tvCurrentTime.setText(SystemUtil.getMediaTime(progress)); 92 | } 93 | } catch (Exception e) { 94 | Log.d("vlc-time", e.toString()); 95 | } 96 | } 97 | 98 | @Override 99 | public void onStartTrackingTouch(SeekBar seekBar) { 100 | 101 | } 102 | 103 | @Override 104 | public void onStopTrackingTouch(SeekBar seekBar) { 105 | 106 | } 107 | }; 108 | 109 | seekBarTime.setOnSeekBarChangeListener(onTimeSeekBarChangeListener); 110 | tvCurrentTime = (TextView) findViewById(R.id.tvCurrentTime); 111 | tvTotalTime = (TextView) findViewById(R.id.tvTotalTime); 112 | imgPlay = (ImageView) findViewById(R.id.imgPlay); 113 | imgPlay.setOnClickListener(new View.OnClickListener() { 114 | @Override 115 | public void onClick(View v) { 116 | if (mediaPlayer.isPlaying()) { 117 | mediaPlayer.pause(); 118 | imgPlay.setBackgroundResource(R.drawable.videoviewx_play); 119 | } else { 120 | mediaPlayer.play(); 121 | imgPlay.setBackgroundResource(R.drawable.videoviewx_pause); 122 | } 123 | } 124 | }); 125 | 126 | LibVLC libvlc = LibVLCUtil.getLibVLC(null); 127 | surfaceHolder.setKeepScreenOn(true); 128 | mediaPlayer = new MediaPlayer(libvlc); 129 | vlcVout = mediaPlayer.getVLCVout(); 130 | callback = new IVLCVout.Callback() { 131 | @Override 132 | public void onNewLayout(IVLCVout ivlcVout, int i, int i1, int i2, int i3, int i4, int i5) { 133 | try { 134 | totalTime = mediaPlayer.getLength(); 135 | seekBarTime.setMax((int) totalTime); 136 | tvTotalTime.setText(SystemUtil.getMediaTime((int) totalTime)); 137 | 138 | videoWidth = i; 139 | videoHight = i1; 140 | 141 | WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 142 | Display display = windowManager.getDefaultDisplay(); 143 | Point point = new Point(); 144 | display.getSize(point); 145 | 146 | ViewGroup.LayoutParams layoutParams = surfaceView.getLayoutParams(); 147 | layoutParams.width = point.x; 148 | layoutParams.height = (int) Math.ceil((float) videoHight * (float) point.x / (float) videoWidth); 149 | surfaceView.setLayoutParams(layoutParams); 150 | } catch (Exception e) { 151 | Log.d("vlc-newlayout", e.toString()); 152 | } 153 | } 154 | 155 | @Override 156 | public void onSurfacesCreated(IVLCVout ivlcVout) { 157 | 158 | } 159 | 160 | @Override 161 | public void onSurfacesDestroyed(IVLCVout ivlcVout) { 162 | 163 | } 164 | }; 165 | vlcVout.addCallback(callback); 166 | vlcVout.setVideoView(surfaceView); 167 | vlcVout.attachViews(); 168 | 169 | Media media; 170 | if (intent.getStringExtra("VideoType").equals("Local")) { 171 | media = new Media(libvlc, intent.getStringExtra("VideoUrl")); 172 | } else { 173 | media = new Media(libvlc, Uri.parse(intent.getStringExtra("VideoUrl"))); 174 | } 175 | 176 | mediaPlayer.setMedia(media); 177 | 178 | eventListener = new MediaPlayer.EventListener() { 179 | @Override 180 | public void onEvent(MediaPlayer.Event event) { 181 | try { 182 | if (event.getTimeChanged() == 0 || totalTime == 0 || event.getTimeChanged() > totalTime) { 183 | return; 184 | } 185 | 186 | seekBarTime.setProgress((int) event.getTimeChanged()); 187 | tvCurrentTime.setText(SystemUtil.getMediaTime((int) event.getTimeChanged())); 188 | 189 | //播放结束 190 | if (mediaPlayer.getPlayerState() == Media.State.Ended) { 191 | seekBarTime.setProgress(0); 192 | mediaPlayer.setTime(0); 193 | tvTotalTime.setText(SystemUtil.getMediaTime((int) totalTime)); 194 | mediaPlayer.stop(); 195 | imgPlay.setBackgroundResource(R.drawable.videoviewx_play); 196 | } 197 | } catch (Exception e) { 198 | Log.d("vlc-event", e.toString()); 199 | } 200 | } 201 | }; 202 | mediaPlayer.setEventListener(eventListener); 203 | 204 | seekBarVolume = (SeekBar) findViewById(R.id.seekBarVolume); 205 | onVolumeSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { 206 | @Override 207 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 208 | if (fromUser) { 209 | mediaPlayer.setVolume(progress); 210 | } 211 | } 212 | 213 | @Override 214 | public void onStartTrackingTouch(SeekBar seekBar) { 215 | 216 | } 217 | 218 | @Override 219 | public void onStopTrackingTouch(SeekBar seekBar) { 220 | 221 | } 222 | }; 223 | seekBarVolume.setOnSeekBarChangeListener(onVolumeSeekBarChangeListener); 224 | 225 | tvFullScreen = (TextView) findViewById(R.id.tvFullScreen); 226 | tvFullScreen.setOnClickListener(new View.OnClickListener() { 227 | @Override 228 | public void onClick(View v) { 229 | isFullScreen = !isFullScreen; 230 | if (isFullScreen) { 231 | tvFullScreen.setText("退出全屏"); 232 | rlHub.setVisibility(View.GONE); 233 | WindowManager.LayoutParams params = getWindow().getAttributes(); 234 | params.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; 235 | getWindow().setAttributes(params); 236 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 237 | } else { 238 | tvFullScreen.setText("全屏"); 239 | rlHub.setVisibility(View.VISIBLE); 240 | WindowManager.LayoutParams params = getWindow().getAttributes(); 241 | params.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); 242 | getWindow().setAttributes(params); 243 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 244 | } 245 | } 246 | }); 247 | 248 | mediaPlayer.play(); 249 | } catch (Exception e) { 250 | Log.d("VideoPlayer", e.toString()); 251 | } 252 | } 253 | 254 | private void pausePlay() { 255 | if (mediaPlayer.isPlaying()) { 256 | mediaPlayer.pause(); 257 | imgPlay.setBackgroundResource(R.drawable.videoviewx_play); 258 | } 259 | 260 | vlcVout.detachViews(); 261 | 262 | seekBarTime.setOnSeekBarChangeListener(null); 263 | seekBarVolume.setOnSeekBarChangeListener(null); 264 | vlcVout.removeCallback(callback); 265 | mediaPlayer.setEventListener(null); 266 | } 267 | 268 | private void resumePlay() { 269 | vlcVout.setVideoView(surfaceView); 270 | vlcVout.attachViews(); 271 | 272 | seekBarTime.setOnSeekBarChangeListener(onTimeSeekBarChangeListener); 273 | seekBarVolume.setOnSeekBarChangeListener(onVolumeSeekBarChangeListener); 274 | vlcVout.addCallback(callback); 275 | mediaPlayer.setEventListener(eventListener); 276 | } 277 | 278 | @Override 279 | protected void onDestroy() { 280 | try { 281 | super.onDestroy(); 282 | 283 | pausePlay(); 284 | mediaPlayer.release(); 285 | } catch (Exception e) { 286 | Log.d("vlc-destroy", e.toString()); 287 | } 288 | } 289 | 290 | @Override 291 | protected void onStop() { 292 | try { 293 | super.onStop(); 294 | 295 | pausePlay(); 296 | } catch (Exception e) { 297 | Log.d("vlc-stop", e.toString()); 298 | } 299 | } 300 | 301 | @Override 302 | protected void onPause() { 303 | try { 304 | super.onPause(); 305 | 306 | pausePlay(); 307 | } catch (Exception e) { 308 | Log.d("vlc-pause", e.toString()); 309 | } 310 | } 311 | 312 | @Override 313 | protected void onResume() { 314 | try { 315 | super.onResume(); 316 | 317 | resumePlay(); 318 | } catch (Exception e) { 319 | Log.d("vlc-resume", e.toString()); 320 | } 321 | } 322 | 323 | @Override 324 | protected void onNewIntent(Intent intent) { 325 | try { 326 | super.onNewIntent(intent); 327 | } catch (Exception e) { 328 | Log.d("vlc-newintent", e.toString()); 329 | } 330 | } 331 | 332 | @Override 333 | public void onBackPressed() { 334 | try { 335 | super.onBackPressed(); 336 | 337 | finish(); 338 | } catch (Exception e) { 339 | Log.d("vlc-back", e.toString()); 340 | } 341 | } 342 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/common_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/player_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/videoviews_seekbar_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/videoviewx_pause.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/videoviewx_play.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/videoviewx_seekbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 19 | 20 |