切换导航
{{systemName}}
{{ info.Title }}
{{info.Title}}
{{ menu.Title }}
{{menu.Title}}
登录
|
退出
搜索
体验安卓原生开发了个播发器,作为后端工程师谈谈我的感受
作者:ych
### 痛点 #### 第三方sdk繁多,依赖和支持兼容问题多 以哔站的开源`ijkplayer`使用为例,教程很多都是过时的 [旧版ijkplayer使用](https://www.jianshu.com/p/c5d972ab0309 "旧版ijkplayer使用") [用ijkplayer播放视频源](https://www.jianshu.com/p/fbafd60d1322 "用ijkplayer播放视频源") 但是下载却找不到包,于是去找githut别人写的[wtplayer](https://github.com/wuhongsheng/wtplayer "wtplayer"),找到`wtplayerlib`类库,拷贝了`libs`文件夹`ijkplayer.jar`等包导入 #### build.gradle依赖繁琐 ``` plugins { id 'com.android.application' } android { compileSdk 32 defaultConfig { applicationId "com.news" minSdk 21 targetSdk 32 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } } dataBinding{ enabled true } buildFeatures { // Enables Jetpack Compose for this module //compose true dataBinding true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation 'com.google.android.exoplayer:exoplayer-core:2.17.0' implementation 'com.google.android.exoplayer:exoplayer-ui:2.17.0' implementation 'com.google.android.exoplayer:exoplayer-hls:2.17.0' implementation 'com.google.android.exoplayer:exoplayer-dash:2.17.0' //哔站的ijkplayer api files('libs/ijkplayer.jar') //implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8' } ``` #### AndroidManifest.xml权限等配置易被遗漏 application内部需要声明`activity`,用户授权`uses-permission`需要添加 ```
``` #### xml控件设计的太渣 用过winform和wpf后使用Android的布局感觉拖控件移动位置不灵活,可能是Android自适应屏幕估计比较难吧,给人的感觉编译器设计的过于粗糙。 ##### activity_main.xml ```
``` ##### activity_record.xml ```
``` ##### activity_video.xml ```
``` ##### activity_ijvideo.xml ```
``` #### 事件实现过于多样 1.Java和Kotlin使用上会纠结 2.Java和Kotlin并不能100%互转 3.很多类库是第三方的被废弃可能性大 4.Kotlin使用后引入bug增多,Google可能直接标记插件废弃 ##### kotlin-android-extensions插件也被废弃了 ``` // btn_update.setOnClickListener(){ // update() // } val updateButton: Button = findViewById(R.id.btn_update) updateButton.setOnClickListener(){ update() } ``` ##### MainActivity.java ``` package com.news; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import android.Manifest; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO},100); } public void record(View view){ startActivity(new Intent(MainActivity.this,MediaRecordActivity.class)); finish(); } public void playVideo(View view){ startActivity(new Intent(this,PlayVideo.class)); } public void playAudio(View view){ startActivity(new Intent(this,IJVideo.class)); } } ``` ##### MediaRecordActivity.java ``` package com.news; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.text.TextUtils; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.Button; import java.io.File; import java.io.IOException; public class MediaRecordActivity extends AppCompatActivity implements View.OnClickListener { private TextureView textureView; private Button btn_opt; private MediaRecorder mediaRecorder; @Override protected void onCreate(@Nullable Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_record); textureView=findViewById(R.id.textureView); btn_opt=findViewById(R.id.btn_opt); btn_opt.setOnClickListener(this); } @Override public void onClick(View v){ CharSequence text=btn_opt.getText(); if(TextUtils.equals(text,"开始")){ btn_opt.setText("结束"); mediaRecorder=new MediaRecorder(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setOutputFile(new File(getExternalFilesDir(""),"a.mp4").getAbsolutePath()); mediaRecorder.setVideoSize(640,480); mediaRecorder.setPreviewDisplay(new Surface(textureView.getSurfaceTexture())); try{ mediaRecorder.prepare(); }catch (IOException e){ e.printStackTrace(); } mediaRecorder.start(); }else{ btn_opt.setText("开始"); mediaRecorder.stop(); mediaRecorder.release(); } } } ``` ##### PlayVideo.java ``` package com.news; import android.Manifest; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.ui.StyledPlayerView; public class PlayVideo extends AppCompatActivity { private static final String URL="http://220.161.87.62:8800/hls/0/index.m3u8"; private ExoPlayer mExoPlayer; private StyledPlayerView mStyledPlayerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video); mStyledPlayerView = findViewById(R.id.exo_player); mExoPlayer = new ExoPlayer.Builder(this).build(); mStyledPlayerView.setPlayer(mExoPlayer); MediaItem mediaItem=MediaItem.fromUri(URL); mExoPlayer.setMediaItem(mediaItem); } @Override protected void onStart(){ super.onStart(); mExoPlayer.prepare(); mExoPlayer.play(); } @Override protected void onStop(){ super.onStop(); mExoPlayer.stop(); mExoPlayer.release(); } } ``` ##### IJVideo.java ``` package com.news; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import tv.danmaku.ijk.media.player.IjkMediaPlayer; public class IJVideo extends AppCompatActivity { private static final String TAG = "MainActivity"; String url = "http://220.161.87.62:8800/hls/0/index.m3u8"; private SurfaceView mSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ijvideo); IjkMediaPlayer player = new IjkMediaPlayer(); mSurfaceView = findViewById(R.id.surface_view); mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { player.setDisplay(holder); Log.d(TAG, "surfaceCreated: "); } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "surfaceChanged: "); } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { Log.d(TAG, "surfaceDestroyed: "); } }); try { player.setDataSource(url); player.prepareAsync(); player.start(); } catch (IOException e) { e.printStackTrace(); } } } ``` 就先这样吧,也算用原生开发了个非常简单的播放器app了吧。
评论区
先去登录
版权所有:机遇屋在线 Copyright © 2021-2025 jiyuwu Co., Ltd.
鲁ICP备16042261号-1