diff --git a/PLDroidPlayerDemo/.gitignore b/PLDroidPlayerDemo/.gitignore
index c6cbe56..afbdab3 100644
--- a/PLDroidPlayerDemo/.gitignore
+++ b/PLDroidPlayerDemo/.gitignore
@@ -1,8 +1,6 @@
-*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
-/captures
diff --git a/PLDroidPlayerDemo/app/build.gradle b/PLDroidPlayerDemo/app/build.gradle
index 0398340..f65a892 100644
--- a/PLDroidPlayerDemo/app/build.gradle
+++ b/PLDroidPlayerDemo/app/build.gradle
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 23
- buildToolsVersion "24.0.0 rc1"
+ compileSdkVersion 22
+ buildToolsVersion "22.0.1"
defaultConfig {
- applicationId "com.pili.pldroid.playerdemo"
+ applicationId "com.pili.android.playerdemo"
minSdkVersion 9
- targetSdkVersion 23
+ targetSdkVersion 22
versionCode 1
versionName "1.0"
}
@@ -20,6 +20,8 @@ android {
}
dependencies {
- compile 'com.android.support:design:23.2.1'
- compile files('libs/pldroid-player-1.2.0.jar')
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:22.0.0'
+ compile files('libs/ijkmediaplayer.jar')
+ compile files('libs/pldroid-player-1.1.6.jar')
}
diff --git a/PLDroidPlayerDemo/app/libs/ijkmediaplayer.jar b/PLDroidPlayerDemo/app/libs/ijkmediaplayer.jar
new file mode 100644
index 0000000..3253d75
Binary files /dev/null and b/PLDroidPlayerDemo/app/libs/ijkmediaplayer.jar differ
diff --git a/PLDroidPlayerDemo/app/libs/pldroid-player-1.1.6.jar b/PLDroidPlayerDemo/app/libs/pldroid-player-1.1.6.jar
new file mode 100644
index 0000000..68e1bb5
Binary files /dev/null and b/PLDroidPlayerDemo/app/libs/pldroid-player-1.1.6.jar differ
diff --git a/PLDroidPlayerDemo/app/libs/pldroid-player-1.2.0.jar b/PLDroidPlayerDemo/app/libs/pldroid-player-1.2.0.jar
deleted file mode 100644
index 474ddb6..0000000
Binary files a/PLDroidPlayerDemo/app/libs/pldroid-player-1.2.0.jar and /dev/null differ
diff --git a/PLDroidPlayerDemo/app/proguard-rules.pro b/PLDroidPlayerDemo/app/proguard-rules.pro
index 6bbda03..ba46e93 100644
--- a/PLDroidPlayerDemo/app/proguard-rules.pro
+++ b/PLDroidPlayerDemo/app/proguard-rules.pro
@@ -1,6 +1,6 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
-# in /Users/lujun/Library/Android/sdk/tools/proguard/proguard-android.txt
+# in /Users/jerikc/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
@@ -15,5 +15,3 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-
--keep class com.pili.pldroid.player.** { *; }
\ No newline at end of file
diff --git a/PLDroidPlayerDemo/app/src/androidTest/java/com/pili/pldroid/playerdemo/ApplicationTest.java b/PLDroidPlayerDemo/app/src/androidTest/java/com/pili/pldroid/playerdemo/ApplicationTest.java
new file mode 100644
index 0000000..b6dedd5
--- /dev/null
+++ b/PLDroidPlayerDemo/app/src/androidTest/java/com/pili/pldroid/playerdemo/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.pili.pldroid.playerdemo;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/PLDroidPlayerDemo/app/src/main/AndroidManifest.xml b/PLDroidPlayerDemo/app/src/main/AndroidManifest.xml
index cdacbcc..115852c 100644
--- a/PLDroidPlayerDemo/app/src/main/AndroidManifest.xml
+++ b/PLDroidPlayerDemo/app/src/main/AndroidManifest.xml
@@ -3,32 +3,46 @@
package="com.pili.pldroid.playerdemo" >
-
+
+
+
+ android:theme="@style/AppTheme" >
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/AudioPlayerActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/AudioPlayerActivity.java
new file mode 100644
index 0000000..bf09459
--- /dev/null
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/AudioPlayerActivity.java
@@ -0,0 +1,197 @@
+package com.pili.pldroid.playerdemo;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import com.pili.pldroid.player.AVOptions;
+import com.pili.pldroid.player.AudioPlayer;
+import com.pili.pldroid.player.PlayerCode;
+import com.pili.pldroid.playerdemo.R;
+import com.pili.pldroid.playerdemo.common.Util;
+import com.pili.pldroid.playerdemo.widget.MediaController;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+import tv.danmaku.ijk.media.player.IjkMediaPlayer;
+
+public class AudioPlayerActivity extends Activity implements
+ IjkMediaPlayer.OnCompletionListener,
+ IjkMediaPlayer.OnInfoListener,
+ IjkMediaPlayer.OnErrorListener,
+ IjkMediaPlayer.OnPreparedListener {
+ private static final String TAG = "AudioPlayerActivity";
+ private static final int REQ_DELAY_MILLS = 3000;
+
+ private View mBufferingIndicator;
+ private MediaController mMediaController;
+ private AudioPlayer mAudioPlayer;
+
+ private String mAudioPath;
+ private Button mBackBtn;
+ private long mLastPosition = 0;
+ private boolean mIsLiveStream = false;
+
+ private int mReqDelayMills = REQ_DELAY_MILLS;
+ private boolean mIsCompleted = false;
+ private Runnable mVideoReconnect;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ setContentView(R.layout.activity_player);
+
+ mAudioPath = getIntent().getStringExtra("audioPath");
+
+ Intent intent = getIntent();
+ String intentAction = intent.getAction();
+ if (!TextUtils.isEmpty(intentAction) && intentAction.equals(Intent.ACTION_VIEW)) {
+ mAudioPath = intent.getDataString();
+ }
+
+ mBackBtn = (Button) findViewById(R.id.back_btn);
+ mBackBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onBackPressed();
+ finish();
+ }
+ });
+ mBufferingIndicator = findViewById(R.id.buffering_indicator);
+
+ boolean useFastForward = true;
+ boolean disableProgressBar = false;
+ // Tip: you can custom the variable depending on your situation
+ mIsLiveStream = true;
+ if (mIsLiveStream) {
+ disableProgressBar = true;
+ useFastForward = false;
+ }
+ mMediaController = new MediaController(this, useFastForward, disableProgressBar);
+ mAudioPlayer = new AudioPlayer(this);
+
+ AVOptions options = new AVOptions();
+ options.setInteger(AVOptions.KEY_MEDIACODEC, 1); // 1 -> enable, 0 -> disable
+
+ Log.i(TAG, "mIsLiveStream:" + mIsLiveStream);
+ if (mIsLiveStream) {
+ options.setInteger(AVOptions.KEY_BUFFER_TIME, 1000); // the unit of buffer time is ms
+ options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 8 * 1000); // the unit of timeout is ms
+ options.setString(AVOptions.KEY_FFLAGS, AVOptions.VALUE_FFLAGS_NOBUFFER); // "nobuffer"
+ options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
+ }
+ mAudioPlayer.setAVOptions(options);
+
+ mMediaController.setMediaPlayer(mAudioPlayer);
+ mAudioPlayer.setMediaController(mMediaController);
+ mAudioPlayer.setOnErrorListener(this);
+ mAudioPlayer.setOnCompletionListener(this);
+ mAudioPlayer.setOnInfoListener(this);
+ mAudioPlayer.setOnPreparedListener(this);
+ mAudioPlayer.setAudioPath(mAudioPath);
+
+ mAudioPlayer.start();
+ mBufferingIndicator.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onCompletion(IMediaPlayer mp) {
+ Log.d(TAG, "onCompletion");
+ mIsCompleted = true;
+ mBufferingIndicator.setVisibility(View.GONE);
+ }
+
+ @Override
+ public boolean onError(IMediaPlayer mp, int what, int extra) {
+ Log.d(TAG, "onError what=" + what + ", extra=" + extra);
+ if (what == -10000) {
+ if (extra == PlayerCode.EXTRA_CODE_INVALID_URI || extra == PlayerCode.EXTRA_CODE_EOF) {
+ if (mBufferingIndicator != null)
+ mBufferingIndicator.setVisibility(View.GONE);
+ return true;
+ }
+ if (mIsCompleted && extra == PlayerCode.EXTRA_CODE_EMPTY_PLAYLIST) {
+ Log.d(TAG, "mVideoView reconnect!!!");
+ mVideoReconnect = new Runnable() {
+ @Override
+ public void run() {
+ mAudioPlayer.setAudioPath(mAudioPath);
+ }
+ };
+ mReqDelayMills += 200;
+ } else if (extra == PlayerCode.EXTRA_CODE_404_NOT_FOUND) {
+ // NO ts exist
+ if (mBufferingIndicator != null)
+ mBufferingIndicator.setVisibility(View.GONE);
+ } else if (extra == PlayerCode.EXTRA_CODE_IO_ERROR) {
+ // NO rtmp stream exist
+ if (mBufferingIndicator != null)
+ mBufferingIndicator.setVisibility(View.GONE);
+ }
+ }
+ // return true means you handle the onError, hence System wouldn't handle it again(popup a dialog).
+ return true;
+ }
+
+ @Override
+ public boolean onInfo(IMediaPlayer mp, int what, int extra) {
+ Log.d(TAG, "onInfo what=" + what + ", extra=" + extra);
+ if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_START) {
+ Log.i(TAG, "onInfo: (MEDIA_INFO_BUFFERING_START)");
+ if (mBufferingIndicator != null)
+ mBufferingIndicator.setVisibility(View.VISIBLE);
+ } else if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_END) {
+ Log.i(TAG, "onInfo: (MEDIA_INFO_BUFFERING_END)");
+ if (mBufferingIndicator != null)
+ mBufferingIndicator.setVisibility(View.GONE);
+ }
+ return true;
+ }
+
+ @Override
+ public void onPrepared(IMediaPlayer mp) {
+ Log.d(TAG, "onPrepared");
+ mBufferingIndicator.setVisibility(View.GONE);
+ mReqDelayMills = REQ_DELAY_MILLS;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mReqDelayMills = REQ_DELAY_MILLS;
+ Log.i(TAG, "onResume");
+ if (mAudioPlayer != null && !mIsLiveStream && mLastPosition != 0) {
+ mAudioPlayer.seekTo(mLastPosition);
+ mAudioPlayer.start();
+ }
+ }
+
+ @Override
+ public void onPause() {
+// if (mAudioPlayer != null) {
+// mAudioPlayer.pause();
+// mLastPosition = mAudioPlayer.getCurrentPosition();
+// }
+ if (mAudioPlayer != null) {
+ mLastPosition = mAudioPlayer.getCurrentPosition();
+ mAudioPlayer.stopPlayback();
+ }
+ super.onPause();
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if(mAudioPlayer.onKeyDown(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/MainActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/MainActivity.java
index ac950be..4e041c7 100644
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/MainActivity.java
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/MainActivity.java
@@ -1,120 +1,168 @@
package com.pili.pldroid.playerdemo;
-import android.app.Activity;
-import android.app.AlertDialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
+import android.database.Cursor;
+import android.provider.MediaStore;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.support.v4.widget.SimpleCursorAdapter;
+import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
-import android.widget.ArrayAdapter;
+import android.widget.AdapterView;
+import android.widget.Button;
import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.TextView;
+import android.widget.ListView;
+import android.widget.Toast;
-public class MainActivity extends AppCompatActivity {
+import com.pili.pldroid.playerdemo.R;
- private static final String DEFAULT_TEST_URL = "rtmp://live.hkstv.hk.lxdns.com/live/hks";
- private Spinner mActivitySpinner;
- private EditText mEditText;
- private int mIsHwCodecEnabled = 0;
+public class MainActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks {
- public static final String[] TEST_ACTIVITY_ARRAY = {
- "PLMediaPlayerActivity",
- "PLAudioPlayerActivity",
- "PLVideoViewActivity",
- "PLVideoTextureActivity",
- "VideoViewActivity"
- };
+ private static final String MSG_NOT_ALLOW_EMPTY_URL = "Error! URL is empty!";
+
+ private ListView fileListView;
+
+ private VideoAdapter adapter;
+
+ private boolean changed = false;
+ private EditText mInputUrlEditText;
+ private Button mVideoBtn;
+ private Button mAudioBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- mEditText = (EditText)findViewById(R.id.VideoPathEdit);
- mEditText.setText(DEFAULT_TEST_URL);
+ fileListView = (ListView) findViewById(R.id.fileListView);
+ adapter = new VideoAdapter(this);
+ fileListView.setAdapter(adapter);
+ fileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, final int position, final long id) {
+ Intent intent = new Intent(MainActivity.this, VideoPlayerActivity.class);
+ intent.putExtra("videoPath", adapter.getVideoPath(position));
+ startActivity(intent);
+ }
+ });
- mActivitySpinner = (Spinner) findViewById(R.id.TestSpinner);
- ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, TEST_ACTIVITY_ARRAY);
- mActivitySpinner.setAdapter(adapter);
- }
+ mInputUrlEditText = (EditText) findViewById(R.id.input_url);
+
+ mVideoBtn = (Button) findViewById(R.id.btn_video);
+ mVideoBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String url = mInputUrlEditText.getText().toString().trim();
+ if (url == null || url.isEmpty()) {
+ Toast.makeText(getApplicationContext(), MSG_NOT_ALLOW_EMPTY_URL, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(MainActivity.this, VideoPlayerActivity.class);
+ intent.putExtra("videoPath", url);
+ startActivity(intent);
+ }
+ });
- public void onClickPlaySetting(View v) {
- showPlaySettingDialog();
+ mAudioBtn = (Button) findViewById(R.id.btn_audio);
+ mAudioBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String url = mInputUrlEditText.getText().toString().trim();
+ if (url == null || url.isEmpty()) {
+ Toast.makeText(getApplicationContext(), MSG_NOT_ALLOW_EMPTY_URL, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(MainActivity.this, AudioPlayerActivity.class);
+ intent.putExtra("audioPath", url);
+ startActivity(intent);
+ }
+ });
+ refreshUI();
+ getSupportLoaderManager().initLoader(1, null, this);
}
- public void onClickLocalFile(View v) {
- Intent intent = new Intent(this, VideoFileActivity.class);
- startActivityForResult(intent, 0);
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
}
- public void onClickPlay(View v) {
- String videopath = mEditText.getText().toString();
- if (!"".equals(videopath)) {
- jumpToPlayerActivity(videopath);
+ private void refreshUI() {
+ if (changed) {
+ fileListView.setVisibility(View.GONE);
+ mInputUrlEditText.setVisibility(View.VISIBLE);
+ mAudioBtn.setVisibility(View.VISIBLE);
+ mVideoBtn.setVisibility(View.VISIBLE);
+ } else {
+ fileListView.setVisibility(View.VISIBLE);
+ mInputUrlEditText.setVisibility(View.GONE);
+ mAudioBtn.setVisibility(View.GONE);
+ mVideoBtn.setVisibility(View.GONE);
}
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
- public void jumpToPlayerActivity(String videopath) {
- Class> cls = null;
- switch (mActivitySpinner.getSelectedItemPosition()) {
- case 0: cls = PLMediaPlayerActivity.class;
- break;
- case 1: cls = PLAudioPlayerActivity.class;
- break;
- case 2: cls = PLVideoViewActivity.class;
- break;
- case 3: cls = PLVideoTextureActivity.class;
- break;
- case 4: cls = VideoViewActivity.class;
- break;
- default:
- return;
+ if (id == R.id.action_change) {
+ changed = !changed;
+ refreshUI();
+ return true;
}
- Intent intent = new Intent(this, cls);
- intent.putExtra("videoPath", videopath);
- intent.putExtra("mediaCodec", mIsHwCodecEnabled);
- startActivity(intent);
+
+ return super.onOptionsItemSelected(item);
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != Activity.RESULT_OK) {
- return;
- }
- String videoPath = data.getStringExtra("videoPath");
- mEditText.setText(videoPath, TextView.BufferType.EDITABLE);
+ public Loader onCreateLoader(int id, Bundle args) {
+ return new CursorLoader(this, MediaStore.Video.Media.getContentUri("external"), null, null, null,
+ "UPPER(" + MediaStore.Video.Media.DATA + ")");
}
- protected void showPlaySettingDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- final View root = inflater.inflate(R.layout.dialog_setting,null);
- final Spinner codecSpinner = (Spinner) root.findViewById(R.id.CodecSpinner);
- codecSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, new String[] {
- getString(R.string.sw_decode), getString(R.string.hw_decode)
- }));
- codecSpinner.setSelection(mIsHwCodecEnabled);
- builder.setTitle(getString(R.string.play_setting));
- builder.setView(root);
- final AlertDialog dialog = builder.create();
- dialog.setCancelable(false);
- dialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.dlg_ok), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mIsHwCodecEnabled = codecSpinner.getSelectedItemPosition();
+ @Override
+ public void onLoadFinished(Loader loader, Cursor data) {
+ adapter.swapCursor(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+
+ }
+
+ class VideoAdapter extends SimpleCursorAdapter {
+ public VideoAdapter(Context context) {
+ super(context, android.R.layout.simple_list_item_2, null,
+ new String[]{MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DATA},
+ new int[]{android.R.id.text1, android.R.id.text2}, 0);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ final Cursor cursor = getCursor();
+ if (cursor.getCount() == 0 || position >= cursor.getCount()) {
+ return 0;
}
- });
- dialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.dlg_cancel), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
+ cursor.moveToPosition(position);
+ return cursor.getLong(0);
+ }
+
+ public String getVideoPath(int position) {
+ final Cursor cursor = getCursor();
+ if (cursor.getCount() == 0) {
+ return "";
}
- });
- dialog.show();
+ cursor.moveToPosition(position);
+
+ return cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
+ }
}
}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLAudioPlayerActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLAudioPlayerActivity.java
deleted file mode 100644
index 672c0cf..0000000
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLAudioPlayerActivity.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package com.pili.pldroid.playerdemo;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
-
-import com.pili.pldroid.player.PLMediaPlayer;
-
-import java.io.IOException;
-
-/**
- * This demo shows how to use PLMediaPlayer API playing audio stream
- */
-public class PLAudioPlayerActivity extends AppCompatActivity {
-
- private static final String TAG = PLAudioPlayerActivity.class.getSimpleName();
-
- private PLMediaPlayer mMediaPlayer;
- private String mAudioPath;
- private View mLoadingView;
- private boolean mIsStopped = false;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_audio_player);
- mLoadingView = findViewById(R.id.LoadingView);
- mAudioPath = getIntent().getStringExtra("videoPath");
-
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- mMediaPlayer = new PLMediaPlayer();
- mMediaPlayer.setOnPreparedListener(mOnPreparedListener);
- mMediaPlayer.setOnCompletionListener(mOnCompletionListener);
- mMediaPlayer.setOnErrorListener(mOnErrorListener);
- mMediaPlayer.setOnInfoListener(mOnInfoListener);
- mMediaPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
-
- prepare();
- }
-
- @Override
- protected void onDestroy() {
- release();
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- audioManager.abandonAudioFocus(null);
- super.onDestroy();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mMediaPlayer.start();
- }
-
- @Override
- protected void onPause() {
- mMediaPlayer.pause();
- super.onPause();
- }
-
- public void onClickPlay(View v) {
- if (mIsStopped) {
- prepare();
- } else {
- mMediaPlayer.start();
- }
- }
-
- public void onClickPause(View v) {
- mMediaPlayer.pause();
- }
-
- public void onClickResume(View v) {
- mMediaPlayer.start();
- }
-
- public void onClickStop(View v) {
- mMediaPlayer.stop();
- mMediaPlayer.reset();
- mIsStopped = true;
- }
-
- public void release() {
- mMediaPlayer.stop();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
-
- private void prepare() {
- try {
- mMediaPlayer.setDataSource(mAudioPath);
- mMediaPlayer.prepareAsync();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- private PLMediaPlayer.OnPreparedListener mOnPreparedListener = new PLMediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(PLMediaPlayer mp) {
- Log.i(TAG, "On Prepared !");
- mMediaPlayer.start();
- mIsStopped = false;
- }
- };
-
- private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {
- @Override
- public boolean onInfo(PLMediaPlayer mp, int what, int extra) {
- Log.i(TAG, "OnInfo, what = " + what + ", extra = " + extra);
- switch (what) {
- case PLMediaPlayer.MEDIA_INFO_BUFFERING_START:
- mLoadingView.setVisibility(View.VISIBLE);
- break;
- case PLMediaPlayer.MEDIA_INFO_BUFFERING_END:
- case PLMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START:
- mLoadingView.setVisibility(View.GONE);
- break;
- default:
- break;
- }
- return true;
- }
- };
-
- private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {
- @Override
- public void onBufferingUpdate(PLMediaPlayer mp, int percent) {
- Log.d(TAG, "onBufferingUpdate: " + percent + "%");
- }
- };
-
- /**
- * Listen the event of playing complete
- * For playing local file, it's called when reading the file EOF
- * For playing network stream, it's called when the buffered bytes played over
- *
- * If setLooping(true) is called, the player will restart automatically
- * And `onCompletion` will not be called
- */
- private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(PLMediaPlayer mp) {
- Log.d(TAG, "Play Completed !");
- }
- };
-
- private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(PLMediaPlayer mp, int errorCode) {
- Log.e(TAG, "Error happened, errorCode = " + errorCode);
- switch (errorCode) {
- case PLMediaPlayer.ERROR_CODE_INVALID_URI:
- break;
- case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:
- break;
- case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:
- break;
- case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:
- break;
- case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:
- break;
- default:
- break;
- }
- // Todo pls handle the error status here, retry or call finish()
- finish();
- // The PLMediaPlayer has moved to the Error state, if you want to retry, must reset first !
- // try {
- // mMediaPlayer.reset();
- // mMediaPlayer.setDataSource(mAudioPath);
- // mMediaPlayer.prepareAsync();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // Return true means the error has been handled
- // If return false, then `onCompletion` will be called
- return true;
- }
- };
-}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLMediaPlayerActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLMediaPlayerActivity.java
deleted file mode 100644
index 6506266..0000000
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLMediaPlayerActivity.java
+++ /dev/null
@@ -1,290 +0,0 @@
-package com.pili.pldroid.playerdemo;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-
-import com.pili.pldroid.player.AVOptions;
-import com.pili.pldroid.player.PLMediaPlayer;
-
-import java.io.IOException;
-
-/**
- * This demo shows how to use PLMediaPlayer API playing video stream
- */
-public class PLMediaPlayerActivity extends AppCompatActivity {
-
- private static final String TAG = PLMediaPlayerActivity.class.getSimpleName();
-
- private SurfaceView mSurfaceView;
- private PLMediaPlayer mMediaPlayer;
- private View mLoadingView;
- private AVOptions mAVOptions;
-
- private int mSurfaceWidth = 0;
- private int mSurfaceHeight = 0;
-
- private String mVideoPath = null;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_media_player);
- mLoadingView = findViewById(R.id.LoadingView);
- mSurfaceView = (SurfaceView) findViewById(R.id.SurfaceView);
- mSurfaceView.getHolder().addCallback(mCallback);
-
- mVideoPath = getIntent().getStringExtra("videoPath");
-
- mAVOptions = new AVOptions();
-
- if (isLiveStreaming(mVideoPath)) {
- // the unit of timeout is ms
- mAVOptions.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);
- // Some optimization with buffering mechanism when be set to 1
- mAVOptions.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
- }
-
- // 1 -> hw codec enable, 0 -> disable [recommended]
- int codec = getIntent().getIntExtra("mediaCodec", 0);
- mAVOptions.setInteger(AVOptions.KEY_MEDIACODEC, codec);
-
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- }
-
- @Override
- protected void onDestroy() {
- release();
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- audioManager.abandonAudioFocus(null);
- super.onDestroy();
- }
-
- public void onClickPlay(View v) {
- prepare();
- }
-
- public void onClickPause(View v) {
- if (mMediaPlayer != null) {
- mMediaPlayer.pause();
- }
- }
-
- public void onClickResume(View v) {
- if (mMediaPlayer != null) {
- mMediaPlayer.start();
- }
- }
-
- public void onClickStop(View v) {
- if (mMediaPlayer != null) {
- mMediaPlayer.stop();
- mMediaPlayer.reset();
- }
- }
-
- public void release() {
- if (mMediaPlayer != null) {
- mMediaPlayer.stop();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- }
-
- private void prepare() {
-
- if (mMediaPlayer != null) {
- release();
- }
-
- try {
- mMediaPlayer = new PLMediaPlayer(mAVOptions);
-
- mMediaPlayer.setOnPreparedListener(mOnPreparedListener);
- mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
- mMediaPlayer.setOnCompletionListener(mOnCompletionListener);
- mMediaPlayer.setOnErrorListener(mOnErrorListener);
- mMediaPlayer.setOnInfoListener(mOnInfoListener);
- mMediaPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
-
- // set replay if completed
- // mMediaPlayer.setLooping(true);
-
- mMediaPlayer.setDataSource(mVideoPath);
- mMediaPlayer.setDisplay(mSurfaceView.getHolder());
- mMediaPlayer.prepareAsync();
-
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- prepare();
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- mSurfaceWidth = width;
- mSurfaceHeight = height;
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- release();
- }
- };
-
- private PLMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = new PLMediaPlayer.OnVideoSizeChangedListener() {
- public void onVideoSizeChanged(PLMediaPlayer mp, int width, int height) {
- Log.i(TAG, "onVideoSizeChanged, width = "+ width + ",height = " + height);
- // resize the display window to fit the screen
- if (width != 0 && height != 0) {
- float ratioW = (float) width/(float) mSurfaceWidth;
- float ratioH = (float) height/(float) mSurfaceHeight;
- float ratio = Math.max(ratioW, ratioH);
- width = (int) Math.ceil((float)width/ratio);
- height = (int) Math.ceil((float)height/ratio);
- FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(width, height);
- layout.gravity = Gravity.CENTER;
- mSurfaceView.setLayoutParams(layout);
- }
- }
- };
-
- private PLMediaPlayer.OnPreparedListener mOnPreparedListener = new PLMediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(PLMediaPlayer mp) {
- Log.i(TAG, "On Prepared !");
- mMediaPlayer.start();
- }
- };
-
- private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {
- @Override
- public boolean onInfo(PLMediaPlayer mp, int what, int extra) {
- Log.i(TAG, "OnInfo, what = " + what + ", extra = " + extra);
- switch (what) {
- case PLMediaPlayer.MEDIA_INFO_BUFFERING_START:
- mLoadingView.setVisibility(View.VISIBLE);
- break;
- case PLMediaPlayer.MEDIA_INFO_BUFFERING_END:
- case PLMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
- mLoadingView.setVisibility(View.GONE);
- break;
- default:
- break;
- }
- return true;
- }
- };
-
- private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {
- @Override
- public void onBufferingUpdate(PLMediaPlayer mp, int percent) {
- Log.d(TAG, "onBufferingUpdate: " + percent + "%");
- }
- };
-
- /**
- * Listen the event of playing complete
- * For playing local file, it's called when reading the file EOF
- * For playing network stream, it's called when the buffered bytes played over
- *
- * If setLooping(true) is called, the player will restart automatically
- * And `onCompletion` will not be called
- *
- */
- private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(PLMediaPlayer mp) {
- Log.d(TAG, "Play Completed !");
- showToastTips("Play Completed !");
- finish();
- }
- };
-
- private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(PLMediaPlayer mp, int errorCode) {
- Log.e(TAG, "Error happened, errorCode = " + errorCode);
- switch (errorCode) {
- case PLMediaPlayer.ERROR_CODE_INVALID_URI:
- showToastTips("Invalid URL !");
- break;
- case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:
- showToastTips("404 resource not found !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:
- showToastTips("Connection refused !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:
- showToastTips("Connection timeout !");
- break;
- case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:
- showToastTips("Empty playlist !");
- break;
- case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:
- showToastTips("Stream disconnected !");
- break;
- case PLMediaPlayer.ERROR_CODE_IO_ERROR:
- showToastTips("Network IO Error !");
- break;
- case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:
- default:
- showToastTips("unknown error !");
- break;
- }
- // Todo pls handle the error status here, retry or call finish()
- finish();
- // The PLMediaPlayer has moved to the Error state, if you want to retry, must reset first !
- // try {
- // mMediaPlayer.reset();
- // mMediaPlayer.setDisplay(mSurfaceView.getHolder());
- // mMediaPlayer.setDataSource(mVideoPath);
- // mMediaPlayer.prepareAsync();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // Return true means the error has been handled
- // If return false, then `onCompletion` will be called
- return true;
- }
- };
-
- private void showToastTips(final String tips) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(PLMediaPlayerActivity.this, tips, Toast.LENGTH_LONG).show();
- }
- });
- }
-
- private boolean isLiveStreaming(String url) {
- if (url.startsWith("rtmp://")
- || (url.startsWith("http://") && url.endsWith(".m3u8"))
- || (url.startsWith("http://") && url.endsWith(".flv"))) {
- return true;
- }
- return false;
- }
-}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoTextureActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoTextureActivity.java
deleted file mode 100644
index b68c22c..0000000
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoTextureActivity.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package com.pili.pldroid.playerdemo;
-
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import com.pili.pldroid.player.AVOptions;
-import com.pili.pldroid.player.PLMediaPlayer;
-import com.pili.pldroid.player.widget.PLVideoTextureView;
-import com.pili.pldroid.playerdemo.widget.MediaController;
-
-/**
- * This is a demo activity of PLVideoTextureView
- */
-public class PLVideoTextureActivity extends AppCompatActivity {
-
- private MediaController mMediaController;
- private PLVideoTextureView mVideoView;
- private Toast mToast = null;
- private String mVideoPath = null;
- private int mRotation = 0;
- private int mDisplayAspectRatio = PLVideoTextureView.ASPECT_RATIO_FIT_PARENT; //default
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setContentView(R.layout.activity_pl_video_texture);
- mVideoView = (PLVideoTextureView) findViewById(R.id.VideoView);
-
- View loadingView = findViewById(R.id.LoadingView);
- mVideoView.setBufferingIndicator(loadingView);
-
- mVideoPath = getIntent().getStringExtra("videoPath");
-
- // If you want to fix display orientation such as landscape, you can use the code show as follow
- //
- // if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- // mVideoView.setPreviewOrientation(0);
- // }
- // else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- // mVideoView.setPreviewOrientation(270);
- // }
-
- mVideoPath = getIntent().getStringExtra("videoPath");
-
- AVOptions options = new AVOptions();
-
- if (isLiveStreaming(mVideoPath)) {
- // the unit of timeout is ms
- options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);
- // Some optimization with buffering mechanism when be set to 1
- options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
- }
-
- // 1 -> hw codec enable, 0 -> disable [recommended]
- int codec = getIntent().getIntExtra("mediaCodec", 0);
- options.setInteger(AVOptions.KEY_MEDIACODEC, codec);
-
- mVideoView.setAVOptions(options);
-
- // You can also use a custom `MediaController` widget
- mMediaController = new MediaController(this, false, isLiveStreaming(mVideoPath));
- mVideoView.setMediaController(mMediaController);
-
- mVideoView.setOnCompletionListener(mOnCompletionListener);
- mVideoView.setOnErrorListener(mOnErrorListener);
-
- // After setVideoPath, the play will start automatically
- mVideoView.setVideoPath(mVideoPath);
- }
-
- @Override
- protected void onPause() {
- mVideoView.pause();
- super.onPause();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mVideoView.start();
- }
-
- @Override
- protected void onDestroy() {
- mVideoView.stopPlayback();
- super.onDestroy();
- }
-
- public void onClickRotate(View v) {
- mRotation = (mRotation + 90) % 360;
- mVideoView.setDisplayOrientation(mRotation);
- }
-
- public void onClickSwitchScreen(View v) {
- mDisplayAspectRatio = (mDisplayAspectRatio + 1) % 5;
- mVideoView.setDisplayAspectRatio(mDisplayAspectRatio);
- switch (mVideoView.getDisplayAspectRatio()) {
- case PLVideoTextureView.ASPECT_RATIO_ORIGIN:
- showToastTips("Origin mode");
- break;
- case PLVideoTextureView.ASPECT_RATIO_FIT_PARENT:
- showToastTips("Fit parent !");
- break;
- case PLVideoTextureView.ASPECT_RATIO_PAVED_PARENT:
- showToastTips("Paved parent !");
- break;
- case PLVideoTextureView.ASPECT_RATIO_16_9:
- showToastTips("16 : 9 !");
- break;
- case PLVideoTextureView.ASPECT_RATIO_4_3:
- showToastTips("4 : 3 !");
- break;
- default:
- break;
- }
- }
-
- private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(PLMediaPlayer mp, int errorCode) {
- switch (errorCode) {
- case PLMediaPlayer.ERROR_CODE_INVALID_URI:
- showToastTips("Invalid URL !");
- break;
- case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:
- showToastTips("404 resource not found !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:
- showToastTips("Connection refused !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:
- showToastTips("Connection timeout !");
- break;
- case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:
- showToastTips("Empty playlist !");
- break;
- case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:
- showToastTips("Stream disconnected !");
- break;
- case PLMediaPlayer.ERROR_CODE_IO_ERROR:
- showToastTips("Network IO Error !");
- break;
- case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:
- default:
- showToastTips("unknown error !");
- break;
- }
- // Todo pls handle the error status here, retry or call finish()
- finish();
- // If you want to retry, do like this:
- // mVideoView.setVideoPath(mVideoPath);
- // Return true means the error has been handled
- // If return false, then `onCompletion` will be called
- return true;
- }
- };
-
- private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(PLMediaPlayer plMediaPlayer) {
- showToastTips("Play Completed !");
- finish();
- }
- };
-
- private void showToastTips(final String tips) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (mToast != null) {
- mToast.cancel();
- }
- mToast = Toast.makeText(PLVideoTextureActivity.this, tips, Toast.LENGTH_SHORT);
- mToast.show();
- }
- });
- }
-
- private boolean isLiveStreaming(String url) {
- if (url.startsWith("rtmp://")
- || (url.startsWith("http://") && url.endsWith(".m3u8"))
- || (url.startsWith("http://") && url.endsWith(".flv"))) {
- return true;
- }
- return false;
- }
-}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoViewActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoViewActivity.java
deleted file mode 100644
index ed0f266..0000000
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/PLVideoViewActivity.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package com.pili.pldroid.playerdemo;
-
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import com.pili.pldroid.player.AVOptions;
-import com.pili.pldroid.player.PLMediaPlayer;
-import com.pili.pldroid.player.widget.PLVideoView;
-import com.pili.pldroid.playerdemo.widget.MediaController;
-
-/**
- * This is a demo activity of PLVideoView
- */
-public class PLVideoViewActivity extends AppCompatActivity {
-
- private static final String TAG = PLVideoViewActivity.class.getSimpleName();
-
- private MediaController mMediaController;
- private PLVideoView mVideoView;
- private Toast mToast = null;
- private String mVideoPath = null;
- private int mDisplayAspectRatio = PLVideoView.ASPECT_RATIO_FIT_PARENT;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_pl_video_view);
- mVideoView = (PLVideoView) findViewById(R.id.VideoView);
-
- View loadingView = findViewById(R.id.LoadingView);
- mVideoView.setBufferingIndicator(loadingView);
-
- mVideoPath = getIntent().getStringExtra("videoPath");
-
- AVOptions options = new AVOptions();
-
- if (isLiveStreaming(mVideoPath)) {
- // the unit of timeout is ms
- options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);
- // Some optimization with buffering mechanism when be set to 1
- options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
- }
-
- // 1 -> hw codec enable, 0 -> disable [recommended]
- int codec = getIntent().getIntExtra("mediaCodec", 0);
- options.setInteger(AVOptions.KEY_MEDIACODEC, codec);
-
- mVideoView.setAVOptions(options);
-
- // Set some listeners
- mVideoView.setOnPreparedListener(mOnPreparedListener);
- mVideoView.setOnInfoListener(mOnInfoListener);
- mVideoView.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
- mVideoView.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
- mVideoView.setOnCompletionListener(mOnCompletionListener);
- mVideoView.setOnSeekCompleteListener(mOnSeekCompleteListener);
- mVideoView.setOnErrorListener(mOnErrorListener);
-
- // After setVideoPath, the play will start automatically
- // mVideoView.start() is not required
- mVideoView.setVideoPath(mVideoPath);
-
- // You can also use a custom `MediaController` widget
- mMediaController = new MediaController(this, false, isLiveStreaming(mVideoPath));
- mVideoView.setMediaController(mMediaController);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mVideoView.start();
- }
-
- @Override
- protected void onPause() {
- mVideoView.pause();
- super.onPause();
- }
-
- @Override
- protected void onDestroy() {
- mVideoView.stopPlayback();
- super.onDestroy();
- }
-
- public void onClickSwitchScreen(View v) {
- mDisplayAspectRatio = (mDisplayAspectRatio + 1) % 5;
- mVideoView.setDisplayAspectRatio(mDisplayAspectRatio);
- switch (mVideoView.getDisplayAspectRatio()) {
- case PLVideoView.ASPECT_RATIO_ORIGIN:
- showToastTips("Origin mode");
- break;
- case PLVideoView.ASPECT_RATIO_FIT_PARENT:
- showToastTips("Fit parent !");
- break;
- case PLVideoView.ASPECT_RATIO_PAVED_PARENT:
- showToastTips("Paved parent !");
- break;
- case PLVideoView.ASPECT_RATIO_16_9:
- showToastTips("16 : 9 !");
- break;
- case PLVideoView.ASPECT_RATIO_4_3:
- showToastTips("4 : 3 !");
- break;
- default:
- break;
- }
- }
-
- private PLMediaPlayer.OnPreparedListener mOnPreparedListener = new PLMediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(PLMediaPlayer plMediaPlayer) {
- Log.d(TAG, "onPrepared ! ");
- }
- };
-
- private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {
- @Override
- public boolean onInfo(PLMediaPlayer plMediaPlayer, int what, int extra) {
- Log.d(TAG, "onInfo: " + what + ", " + extra);
- return false;
- }
- };
-
- private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(PLMediaPlayer plMediaPlayer, int errorCode) {
- Log.e(TAG, "Error happened, errorCode = " + errorCode);
- switch (errorCode) {
- case PLMediaPlayer.ERROR_CODE_INVALID_URI:
- showToastTips("Invalid URL !");
- break;
- case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:
- showToastTips("404 resource not found !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:
- showToastTips("Connection refused !");
- break;
- case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:
- showToastTips("Connection timeout !");
- break;
- case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:
- showToastTips("Empty playlist !");
- break;
- case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:
- showToastTips("Stream disconnected !");
- break;
- case PLMediaPlayer.ERROR_CODE_IO_ERROR:
- showToastTips("Network IO Error !");
- break;
- case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:
- default:
- showToastTips("unknown error !");
- break;
- }
- // Todo pls handle the error status here, retry or call finish()
- finish();
- // If you want to retry, do like this:
- // mVideoView.setVideoPath(mVideoPath);
- // Return true means the error has been handled
- // If return false, then `onCompletion` will be called
- return true;
- }
- };
-
- private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(PLMediaPlayer plMediaPlayer) {
- Log.d(TAG, "Play Completed !");
- showToastTips("Play Completed !");
- finish();
- }
- };
-
- private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {
- @Override
- public void onBufferingUpdate(PLMediaPlayer plMediaPlayer, int precent) {
- Log.d(TAG, "onBufferingUpdate: " + precent);
- }
- };
-
- private PLMediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new PLMediaPlayer.OnSeekCompleteListener() {
- @Override
- public void onSeekComplete(PLMediaPlayer plMediaPlayer) {
- Log.d(TAG, "onSeekComplete !");
- };
- };
-
- private PLMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = new PLMediaPlayer.OnVideoSizeChangedListener() {
- @Override
- public void onVideoSizeChanged(PLMediaPlayer plMediaPlayer, int width, int height) {
- Log.d(TAG, "onVideoSizeChanged: " + width + "," + height);
- }
- };
-
- private void showToastTips(final String tips) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (mToast != null) {
- mToast.cancel();
- }
- mToast = Toast.makeText(PLVideoViewActivity.this, tips, Toast.LENGTH_SHORT);
- mToast.show();
- }
- });
- }
-
- private boolean isLiveStreaming(String url) {
- if (url.startsWith("rtmp://")
- || (url.startsWith("http://") && url.endsWith(".m3u8"))
- || (url.startsWith("http://") && url.endsWith(".flv"))) {
- return true;
- }
- return false;
- }
-}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoFileActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoFileActivity.java
deleted file mode 100644
index 5415938..0000000
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoFileActivity.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.pili.pldroid.playerdemo;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.CursorLoader;
-import android.support.v4.content.Loader;
-import android.support.v4.widget.SimpleCursorAdapter;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
-
-public class VideoFileActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {
-
- private ListView mVideoListView;
- private VideoAdapter mVideoAdapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_video_file);
-
- mVideoListView = (ListView) findViewById(R.id.FileListView);
- mVideoAdapter = new VideoAdapter(this);
-
- mVideoListView.setAdapter(mVideoAdapter);
- mVideoListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, final int position, final long id) {
- Intent intent = new Intent();
- intent.putExtra("videoPath", mVideoAdapter.getVideoPath(position));
- setResult(Activity.RESULT_OK, intent);
- finish();
- }
- });
-
- getSupportLoaderManager().initLoader(1, null, this);
- }
-
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- return new CursorLoader(this, MediaStore.Video.Media.getContentUri("external"), null, null, null,
- "UPPER(" + MediaStore.Video.Media.DATA + ")");
- }
-
- @Override
- public void onLoadFinished(Loader loader, Cursor data) {
- mVideoAdapter.swapCursor(data);
- }
-
- @Override
- public void onLoaderReset(Loader loader) {
-
- }
-
- public class VideoAdapter extends SimpleCursorAdapter {
-
- public VideoAdapter(Context context) {
- super(context, android.R.layout.simple_list_item_1, null,
- new String[]{MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DATA},
- new int[]{android.R.id.text1, android.R.id.text2}, 0);
- }
-
- @Override
- public long getItemId(int position) {
- final Cursor cursor = getCursor();
- if (cursor == null || cursor.getCount() == 0 || position >= cursor.getCount()) {
- return 0;
- }
- cursor.moveToPosition(position);
- return cursor.getLong(0);
- }
-
- public String getVideoPath(int position) {
- final Cursor cursor = getCursor();
- if (cursor.getCount() == 0) {
- return "";
- }
- cursor.moveToPosition(position);
- return cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
- }
- }
-
-}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoViewActivity.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoPlayerActivity.java
similarity index 87%
rename from PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoViewActivity.java
rename to PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoPlayerActivity.java
index 13bcbfd..1ad03a9 100644
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoViewActivity.java
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/VideoPlayerActivity.java
@@ -1,9 +1,10 @@
package com.pili.pldroid.playerdemo;
+import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -15,8 +16,8 @@
import com.pili.pldroid.player.AVOptions;
import com.pili.pldroid.player.PlayerCode;
+import com.pili.pldroid.player.SharedLibraryNameHelper;
import com.pili.pldroid.player.common.Util;
-import com.pili.pldroid.player.widget.PLVideoView;
import com.pili.pldroid.player.widget.VideoView;
import com.pili.pldroid.playerdemo.widget.AspectLayout;
import com.pili.pldroid.playerdemo.widget.MediaController;
@@ -24,19 +25,13 @@
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
-/**
- * This is a demo activity of com.pili.pldroid.player.widget.VideoView
- * @deprecated Use {@link PLVideoView} instead.
- */
-public class VideoViewActivity extends AppCompatActivity implements
+public class VideoPlayerActivity extends Activity implements
IjkMediaPlayer.OnCompletionListener,
IjkMediaPlayer.OnInfoListener,
IjkMediaPlayer.OnErrorListener,
IjkMediaPlayer.OnVideoSizeChangedListener,
- IjkMediaPlayer.OnPreparedListener {
-
- private static final String TAG = "VideoViewActivity";
-
+ IjkMediaPlayer.OnPreparedListener{
+ private static final String TAG = "VideoPlayerActivity";
private static final int REQ_DELAY_MILLS = 3000;
private VideoView mVideoView;
@@ -59,9 +54,7 @@ public class VideoViewActivity extends AppCompatActivity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- setContentView(R.layout.activity_video_view);
-
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ setContentView(R.layout.activity_player);
mVideoPath = getIntent().getStringExtra("videoPath");
@@ -71,9 +64,7 @@ protected void onCreate(Bundle savedInstanceState) {
mVideoPath = intent.getDataString();
}
- mVideoView = (VideoView) findViewById(R.id.video_view);
mAspectLayout = (AspectLayout)findViewById(R.id.aspect_layout);
- mBufferingIndicator = findViewById(R.id.buffering_indicator);
mBackBtn = (Button) findViewById(R.id.back_btn);
mBackBtn.setOnClickListener(new View.OnClickListener() {
@@ -84,33 +75,40 @@ public void onClick(View view) {
finish();
}
});
-
+ mBufferingIndicator = findViewById(R.id.buffering_indicator);
boolean useFastForward = true;
boolean disableProgressBar = false;
Log.i(TAG, "mVideoPath:" + mVideoPath);
-
- //SharedLibraryNameHelper.getInstance().renameSharedLibrary("pldroidplayer_v7a");
-
- AVOptions options = new AVOptions();
- int codec = getIntent().getIntExtra("mediaCodec", 0);
- options.setInteger(AVOptions.KEY_MEDIACODEC, codec); // 1 -> hw codec enable, 0 -> disable
-
- mIsLiveStream = isLiveStreaming(mVideoPath);
- if (mIsLiveStream) {
- options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000); // the unit of timeout is ms
- options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
- }
// Tip: you can custom the variable depending on your situation
+ mIsLiveStream = true;
if (mIsLiveStream) {
disableProgressBar = true;
useFastForward = false;
}
mMediaController = new MediaController(this, useFastForward, disableProgressBar);
+
+// SharedLibraryNameHelper.getInstance().renameSharedLibrary("pldroidplayer_v7a");
+
+// mVideoView = (VideoTextureView) findViewById(R.id.video_view);
+ mVideoView = (VideoView) findViewById(R.id.video_view);
+// mVideoView.setVideoPath(mVideoPath);
+// mVideoView.start();
mMediaController.setMediaPlayer(mVideoView);
mVideoView.setMediaController(mMediaController);
mVideoView.setMediaBufferingIndicator(mBufferingIndicator);
+ AVOptions options = new AVOptions();
+ options.setInteger(AVOptions.KEY_MEDIACODEC, 0); // 1 -> enable, 0 -> disable
+
+ Log.i(TAG, "mIsLiveStream:" + mIsLiveStream);
+ if (mIsLiveStream) {
+ options.setInteger(AVOptions.KEY_BUFFER_TIME, 1000); // the unit of buffer time is ms
+ options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000); // the unit of timeout is ms
+ options.setString(AVOptions.KEY_FFLAGS, AVOptions.VALUE_FFLAGS_NOBUFFER); // "nobuffer"
+ options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
+ }
+
mVideoView.setAVOptions(options);
mVideoView.setVideoPath(mVideoPath);
@@ -122,7 +120,7 @@ public void onClick(View view) {
mVideoView.setOnVideoSizeChangedListener(this);
mVideoView.requestFocus();
-
+// mVideoView.start();
mBufferingIndicator.setVisibility(View.VISIBLE);
}
@@ -170,9 +168,9 @@ public void run() {
@Override
public boolean onInfo(IMediaPlayer mp, int what, int extra) {
-
Log.d(TAG, "onInfo what=" + what + ", extra=" + extra);
+
if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_START) {
Log.i(TAG, "onInfo: (MEDIA_INFO_BUFFERING_START)");
if (mBufferingIndicator != null)
@@ -188,7 +186,6 @@ public boolean onInfo(IMediaPlayer mp, int what, int extra) {
Toast.makeText(this, "Video Start", Toast.LENGTH_LONG).show();
Log.i(TAG, "duration:" + mVideoView.getDuration());
}
-
return true;
}
@@ -215,25 +212,22 @@ public void onPause() {
mLastPosition = mVideoView.getCurrentPosition();
mVideoView.pause();
}
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onPause();
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
@Override
public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height, int sarNum, int sarDen) {
-
Log.i(TAG, "onVideoSizeChanged " + iMediaPlayer.getVideoWidth() + "x" + iMediaPlayer.getVideoHeight() + ",width:" + width + ",height:" + height + ",sarDen:" + sarDen + ",sarNum:" + sarNum);
-
- /*
if (width > height) {
// land video
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ mScreenSize = Util.getResolution(this);
} else {
// port video
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
- }*/
-
- mScreenSize = Util.getResolution(this);
+ mScreenSize = Util.getResolution(this);
+ }
if (width < mScreenSize.first) {
height = mScreenSize.first * height / width;
@@ -250,13 +244,4 @@ public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height,
mLayoutParams.height = height;
mAspectLayout.setLayoutParams(mLayoutParams);
}
-
- private boolean isLiveStreaming(String url) {
- if (url.startsWith("rtmp://")
- || (url.startsWith("http://") && url.endsWith(".m3u8"))
- || (url.startsWith("http://") && url.endsWith(".flv"))) {
- return true;
- }
- return false;
- }
}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/common/Util.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/common/Util.java
new file mode 100644
index 0000000..3358e02
--- /dev/null
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/common/Util.java
@@ -0,0 +1,16 @@
+package com.pili.pldroid.playerdemo.common;
+
+import android.net.Uri;
+
+/**
+ * Created by jerikc on 15/5/30.
+ */
+public class Util {
+ public static boolean isUrlLocalFile(String path) {
+ return getPathScheme(path) == null || "file".equals(getPathScheme(path));
+ }
+
+ public static String getPathScheme(String path) {
+ return Uri.parse(path).getScheme();
+ }
+}
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/AspectLayout.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/AspectLayout.java
index c4d65d4..5c04048 100644
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/AspectLayout.java
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/AspectLayout.java
@@ -15,7 +15,6 @@
* Created by jerikc on 15/11/22.
*/
public class AspectLayout extends RelativeLayout {
-
private static final String TAG = "AspectLayout";
private int mWidthMeasureSpec;
diff --git a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/MediaController.java b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/MediaController.java
index 0a943fb..1fe0a66 100644
--- a/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/MediaController.java
+++ b/PLDroidPlayerDemo/app/src/main/java/com/pili/pldroid/playerdemo/widget/MediaController.java
@@ -27,13 +27,11 @@
import java.util.Locale;
/**
- * You can write a custom MediaController instead of this class
- * A MediaController widget must implement all the interface defined by com.pili.pldroid.player.IMediaController
+ * Created by jerikc on 15/5/29.
*/
public class MediaController extends FrameLayout implements IMediaController {
-
- private static final String TAG = "PLMediaController";
- private IMediaController.MediaPlayerControl mPlayer;
+ private static final String TAG = "MyMediaController";
+ private MediaPlayerControl mPlayer;
private Context mContext;
private PopupWindow mWindow;
private int mAnimStyle;
@@ -75,6 +73,7 @@ public class MediaController extends FrameLayout implements IMediaController {
private Runnable mLastSeekBarRunnable;
private boolean mDisableProgress = false;
+
public MediaController(Context context, AttributeSet attrs) {
super(context, attrs);
mRoot = this;
@@ -110,7 +109,6 @@ private boolean initController(Context context) {
public void onFinishInflate() {
if (mRoot != null)
initControllerView(mRoot);
- super.onFinishInflate();
}
private void initFloatingWindow() {
@@ -377,7 +375,7 @@ public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
if (!fromuser)
return;
- final int newposition = (int) (mDuration * progress) / 1000;
+ final long newposition = (mDuration * progress) / 1000;
String time = generateTime(newposition);
if (mInstantSeeking) {
mHandler.removeCallbacks(mLastSeekBarRunnable);
@@ -395,7 +393,7 @@ public void run() {
public void onStopTrackingTouch(SeekBar bar) {
if (!mInstantSeeking)
- mPlayer.seekTo((int)(mDuration * bar.getProgress()) / 1000);
+ mPlayer.seekTo((mDuration * bar.getProgress()) / 1000);
show(sDefaultTimeout);
mHandler.removeMessages(SHOW_PROGRESS);
@@ -405,9 +403,9 @@ public void onStopTrackingTouch(SeekBar bar) {
}
};
- private OnClickListener mRewListener = new OnClickListener() {
+ private View.OnClickListener mRewListener = new View.OnClickListener() {
public void onClick(View v) {
- int pos = (int)mPlayer.getCurrentPosition();
+ long pos = mPlayer.getCurrentPosition();
pos -= 5000; // milliseconds
mPlayer.seekTo(pos);
setProgress();
@@ -416,9 +414,9 @@ public void onClick(View v) {
}
};
- private OnClickListener mFfwdListener = new OnClickListener() {
+ private View.OnClickListener mFfwdListener = new View.OnClickListener() {
public void onClick(View v) {
- int pos = (int)mPlayer.getCurrentPosition();
+ long pos = mPlayer.getCurrentPosition();
pos += 15000; // milliseconds
mPlayer.seekTo(pos);
setProgress();
@@ -530,7 +528,7 @@ public void hide() {
if (mShowing) {
if (mAnchor != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- //mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+ mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
try {
diff --git a/PLDroidPlayerDemo/app/src/main/jniLibs/arm64-v8a/libpldroidplayer.so b/PLDroidPlayerDemo/app/src/main/jniLibs/arm64-v8a/libpldroidplayer.so
old mode 100644
new mode 100755
index d16e20e..6905807
Binary files a/PLDroidPlayerDemo/app/src/main/jniLibs/arm64-v8a/libpldroidplayer.so and b/PLDroidPlayerDemo/app/src/main/jniLibs/arm64-v8a/libpldroidplayer.so differ
diff --git a/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi-v7a/libpldroidplayer.so b/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi-v7a/libpldroidplayer.so
old mode 100644
new mode 100755
index 8d72925..06ca5fb
Binary files a/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi-v7a/libpldroidplayer.so and b/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi-v7a/libpldroidplayer.so differ
diff --git a/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi/libpldroidplayer.so b/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi/libpldroidplayer.so
old mode 100644
new mode 100755
index 525bc53..02e0270
Binary files a/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi/libpldroidplayer.so and b/PLDroidPlayerDemo/app/src/main/jniLibs/armeabi/libpldroidplayer.so differ
diff --git a/PLDroidPlayerDemo/app/src/main/jniLibs/x86/libpldroidplayer.so b/PLDroidPlayerDemo/app/src/main/jniLibs/x86/libpldroidplayer.so
old mode 100644
new mode 100755
index 70610ff..0e5e164
Binary files a/PLDroidPlayerDemo/app/src/main/jniLibs/x86/libpldroidplayer.so and b/PLDroidPlayerDemo/app/src/main/jniLibs/x86/libpldroidplayer.so differ
diff --git a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/audio.jpg b/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/audio.jpg
deleted file mode 100644
index 44550fd..0000000
Binary files a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/audio.jpg and /dev/null differ
diff --git a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_rotate_right.png b/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_rotate_right.png
deleted file mode 100644
index abc89e6..0000000
Binary files a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_rotate_right.png and /dev/null differ
diff --git a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_switch_screen.png b/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_switch_screen.png
deleted file mode 100644
index 52601b0..0000000
Binary files a/PLDroidPlayerDemo/app/src/main/res/drawable-hdpi/ic_switch_screen.png and /dev/null differ
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_audio_player.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_audio_player.xml
index e93ac3b..28bf83a 100644
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_audio_player.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/layout/activity_audio_player.xml
@@ -1,40 +1,53 @@
-
-
+
-
+
+
+
+
+
+
+ android:layout_height="wrap_content" />
-
+ android:focusable="false"
+ android:focusableInTouchMode="false"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
-
-
-
+ android:layout_gravity="center"
+ android:adjustViewBounds="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="0"
+ android:scaleType="centerInside"
+ android:singleLine="true"
+ android:text="@string/buffering"
+ android:textSize="12sp" />
-
+
+
+
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_main.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_main.xml
index dc9f204..00f1956 100644
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_main.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/layout/activity_main.xml
@@ -1,78 +1,40 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:id="@+id/fileListView"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:visibility="gone"
+ android:choiceMode="singleChoice"/>
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_media_player.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_media_player.xml
deleted file mode 100644
index 3fdac22..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_media_player.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_texture.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_texture.xml
deleted file mode 100644
index ef81416..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_texture.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_view.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_view.xml
deleted file mode 100644
index e3c2912..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_pl_video_view.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/activity_video_view.xml b/PLDroidPlayerDemo/app/src/main/res/layout/activity_player.xml
similarity index 93%
rename from PLDroidPlayerDemo/app/src/main/res/layout/activity_video_view.xml
rename to PLDroidPlayerDemo/app/src/main/res/layout/activity_player.xml
index 8fec569..6861555 100644
--- a/PLDroidPlayerDemo/app/src/main/res/layout/activity_video_view.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/layout/activity_player.xml
@@ -13,11 +13,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
+
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
- />
+ />
+ android:layout_height="wrap_content" />
+ android:visibility="gone" >
+
+
-
-
-
-
-
\ No newline at end of file
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/dialog_setting.xml b/PLDroidPlayerDemo/app/src/main/res/layout/dialog_setting.xml
deleted file mode 100644
index 4da950f..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/layout/dialog_setting.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/PLDroidPlayerDemo/app/src/main/res/layout/layout_buttons.xml b/PLDroidPlayerDemo/app/src/main/res/layout/layout_buttons.xml
deleted file mode 100644
index 7e6c66c..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/layout/layout_buttons.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/menu/menu_audio_player.xml b/PLDroidPlayerDemo/app/src/main/res/menu/menu_audio_player.xml
new file mode 100644
index 0000000..93eca95
--- /dev/null
+++ b/PLDroidPlayerDemo/app/src/main/res/menu/menu_audio_player.xml
@@ -0,0 +1,7 @@
+
diff --git a/PLDroidPlayerDemo/app/src/main/res/menu/menu_main.xml b/PLDroidPlayerDemo/app/src/main/res/menu/menu_main.xml
index 3bb7dce..deff29f 100644
--- a/PLDroidPlayerDemo/app/src/main/res/menu/menu_main.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/menu/menu_main.xml
@@ -1,10 +1,9 @@
diff --git a/PLDroidPlayerDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/PLDroidPlayerDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index aee44e1..0000000
Binary files a/PLDroidPlayerDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/PLDroidPlayerDemo/app/src/main/res/values-v21/styles.xml b/PLDroidPlayerDemo/app/src/main/res/values-v21/styles.xml
deleted file mode 100644
index dbbdd40..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/values-v21/styles.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/values/colors.xml b/PLDroidPlayerDemo/app/src/main/res/values/colors.xml
deleted file mode 100644
index 3ab3e9c..0000000
--- a/PLDroidPlayerDemo/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- #3F51B5
- #303F9F
- #FF4081
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/values/dimens.xml b/PLDroidPlayerDemo/app/src/main/res/values/dimens.xml
index 812cb7b..47c8224 100644
--- a/PLDroidPlayerDemo/app/src/main/res/values/dimens.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/values/dimens.xml
@@ -2,5 +2,4 @@
16dp
16dp
- 16dp
diff --git a/PLDroidPlayerDemo/app/src/main/res/values/strings.xml b/PLDroidPlayerDemo/app/src/main/res/values/strings.xml
index 8431a76..ee4ad19 100644
--- a/PLDroidPlayerDemo/app/src/main/res/values/strings.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/values/strings.xml
@@ -1,5 +1,7 @@
PLDroidPlayerDemo
+
+ Hello world!
Settings
OK
@@ -10,25 +12,4 @@
AudioPlayerActivity
Video
Audio
-
- 播放设置
- 解码配置
- 软件解码
- 硬件解码
-
- OK
- Cancel
-
- [请选择测试 Activity]:
- [输入或选择视频地址]:
- 手动输入测试视频地址
- 本地文件
- 播放配置
- 点击播放
-
- 开始
- 暂停
- 继续
- 停止
-
diff --git a/PLDroidPlayerDemo/app/src/main/res/values/styles.xml b/PLDroidPlayerDemo/app/src/main/res/values/styles.xml
index dba2f0d..91eb77f 100644
--- a/PLDroidPlayerDemo/app/src/main/res/values/styles.xml
+++ b/PLDroidPlayerDemo/app/src/main/res/values/styles.xml
@@ -3,24 +3,9 @@
-
-
-
-
-
-
-
-
-
diff --git a/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.jar b/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.jar
index 13372ae..8c0fb64 100644
Binary files a/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.jar and b/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.properties b/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.properties
index 3cb30e1..0c71e76 100644
--- a/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.properties
+++ b/PLDroidPlayerDemo/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Mon Dec 28 10:00:20 PST 2015
+#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/PLDroidPlayerDemo/gradlew b/PLDroidPlayerDemo/gradlew
index 9d82f78..91a7e26 100755
--- a/PLDroidPlayerDemo/gradlew
+++ b/PLDroidPlayerDemo/gradlew
@@ -42,6 +42,11 @@ case "`uname`" in
;;
esac
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -56,9 +61,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
+cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -109,7 +114,6 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
diff --git a/README.md b/README.md
index fa7cbe4..597698b 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,34 @@
# PLDroidPlayer
+PLDroidPlayer 是一个适用于 Android 的音视频播放器 SDK,可高度定制化和二次开发,特色是支持 RTMP 和 HLS 直播流媒体、以及常见音视频文件(如 MP4、M4A )播放。
-PLDroidPlayer 是一个适用于 Android 平台的音视频播放器 SDK,可高度定制化和二次开发,为 Android 开发者提供了简单、快捷的接口,帮助开发者在 Android 平台上快速开发播放器应用。
+# 功能特性
+ - [x] 基于 [ijkplayer](https://github.com/Bilibili/ijkplayer) ( based on [ffplay](http://ffmpeg.org/) )
+ - [x] Android Min API 9
+ - [x] 支持 RTMP, HLS 协议
+ - [x] 支持 ARM, ARM v7a, ARM64 v8a, x86
+ - [x] 支持 MediaCodec 硬解码
+ - [x] 支持纯音频播放,并支持后台运行
+ - [x] 提供 `VideoView` 控件
+ - [x] 可定制化的 `MediaController`
+ - [x] 支持 `seekTo()`
+ - [x] 支持获取当前播放时长 `getDuration()`
+ - [x] 支持获取当前播放的位置 `getCurrentPosition()`
+ - [x] 支持音量控制 `setVolume()`
+ - [x] 提供如下接口:
+ - `OnPreparedListener`
+ - `OnCompletionListener`
+ - `OnErrorListener`
+ - `OnInfoListener`
+
+# 内容摘要
+- [播放器对比](#播放器对比)
+- [使用方法](#使用方法)
+ - [配置工程](#项目配置)
+ - [示例代码](#示例代码)
+- [依赖库](#依赖库)
+- [版本历史](#版本历史)
-## 特性
-- [x] 基于 [ijkplayer](https://github.com/Bilibili/ijkplayer) ( based on [ffplay](http://ffmpeg.org/) )
-- [x] Android Min API 9
-- [x] 支持 RTMP 和 HLS 协议的直播流媒体播放
-- [x] 支持常见的音视频文件播放(MP4、M4A、flv 等)
-- [x] 支持 MediaCodec 硬件解码
-- [x] 提供播放器核心类 `PLMediaPlayer`
-- [x] 提供 `PLVideoView` 控件
-- [x] 提供 `PLVideoTextureView` 控件
-- [x] 支持多种画面预览模式
-- [x] 支持画面旋转(0度,90度,180度,270度)
-- [x] 支持纯音频播放,并支持后台运行
-- [x] 可高度定制化的 `MediaController`
-- [x] 支持 ARM, ARMv7a, ARM64v8a, X86 主流芯片体系架构
## 播放器对比
| - | ijkplayer | PLDroidPlayer |
@@ -26,12 +38,181 @@ PLDroidPlayer 是一个适用于 Android 平台的音视频播放器 SDK,可
|Widget|有商业授权风险|无商业授权风险|
|MediaController|难以定制化|容易定制化|
-## SDK 最低要求
+## 使用方法
+### 项目配置
+从 `releases/` 目录获取:
+
+- pldroid-player-xxx.jar
+- ijkmediaplayer-xxx.jar
+- armeabi-v7a/libpldroidplayer.so
+- arm64-v8a/libpldroidplayer.so
+- armeabi/libpldroidplayer.so
+- x86/libpldroidplayer.so
-Android 2.3 (API 9) 及其以上
+并在项目中加入对应的 jar/so 文件的依赖关系。可参考 [PLDroidPlayerDemo][1] 中的做法。
-## 使用方法
-请参考 wiki 文档:[PLDroidPlayer 开发指南](https://github.com/pili-engineering/PLDroidPlayer/wiki)
+### 示例代码
+#### Video 播放
+
+1 初始化 VideoView 及其布局
+```XML
+
+```
+```JAVA
+ mVideoView = (VideoView) findViewById(R.id.video_view);
+```
+
+2 VideoView 与 MediaController 建立联系
+```JAVA
+ mMediaController.setMediaPlayer(mVideoView);
+ mVideoView.setMediaController(mMediaController);
+```
+
+3 传入播放地址,可以是 `/path/to/local.mp4` 本地文件绝对路径,或 HLS URL,或 RTMP URL
+```JAVA
+ mVideoView.setVideoPath(mVideoPath);
+```
+
+4 设置 Listener
+```JAVA
+public class VideoPlayerActivity extends Activity implements
+ OnCompletionListener,
+ OnInfoListener,
+ OnVideoSizeChangedListener,
+ OnErrorListener,
+ OnPreparedListener {
+...
+ mVideoView.setOnErrorListener(this);
+ mVideoView.setOnCompletionListener(this);
+ mVideoView.setOnInfoListener(this);
+ mVideoView.setOnPreparedListener(this);
+ mVideoView.setOnVideoSizeChangedListener(this);
+...
+
+@Override
+public void onCompletion(IMediaPlayer mp) {
+ ...
+}
+
+@Override
+public boolean onError(IMediaPlayer mp, int what, int extra) {
+ if (what == -10000) {
+ switch (extra) {
+ case PlayerCode.EXTRA_CODE_404_NOT_FOUND:
+ break;
+ case PlayerCode.EXTRA_CODE_CONNECTION_REFUSED:
+ break;
+ case PlayerCode.EXTRA_CODE_CONNECTION_TIMEOUT:
+ break;
+ case PlayerCode.EXTRA_CODE_EMPTY_PLAYLIST:
+ break;
+ case PlayerCode.EXTRA_CODE_INVALID_URI:
+ break;
+ case PlayerCode.EXTRA_CODE_IO_ERROR:
+ break;
+ case PlayerCode.EXTRA_CODE_STREAM_DISCONNECTED:
+ break;
+ }
+ }
+}
+
+@Override
+public boolean onInfo(IMediaPlayer mp, int what, int extra) {
+ switch (what) {
+ case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
+ break;
+ case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
+ break;
+ case IMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START:
+ break;
+ case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
+ break;
+ }
+}
+
+@Override
+public void onPrepared(IMediaPlayer mp) {
+ ...
+}
+
+@Override
+public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height, int sarNum, int sarDen) {
+ ...
+}
+```
+
+
+
+5 设置 `AVOptions`
+```JAVA
+// Tip: you can custom the variable depending on your situation
+if (mIsLiveStream) {
+ options.setInteger(AVOptions.KEY_BUFFER_TIME, 1000); // the unit of buffer time is ms
+ options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000); // the unit of timeout is ms
+ options.setString(AVOptions.KEY_FFLAGS, AVOptions.VALUE_FFLAGS_NOBUFFER); // "nobuffer"
+ options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
+}
+mAudioPlayer.setAVOptions(options);
+```
+> `AVOptions.KEY_FFLAGS` , `AVOptions.KEY_BUFFER_TIME` 仅对 RTMP 有效;`AVOptions` 需要在 `start()`/`setVideoPath()` 前设置
+
+6 全屏播放
+
+您只需在 `VideoView` 的布局文件中设置对应的属性即可,例如:
+
+```
+
+```
+
+#### 纯音频播放
+1 实例化 `AudioPlayer`
+```JAVA
+mAudioPlayer = new AudioPlayer(this);
+```
+
+2 `AudioPlayer` 与 `MediaController` 建立联系
+```JAVA
+mMediaController.setMediaPlayer(mAudioPlayer);
+mAudioPlayer.setMediaController(mMediaController);
+```
+
+3 传入播放地址,可以是 `/path/to/local.mp3` 本地音频文件绝对路径,或 HLS URL,或 RTMP URL
+```JAVA
+mAudioPlayer.setAudioPath(mAudioPath);
+```
+
+4 设置 Listener
+```JAVA
+mAudioPlayer.setOnErrorListener(this);
+mAudioPlayer.setOnCompletionListener(this);
+mAudioPlayer.setOnInfoListener(this);
+mAudioPlayer.setOnPreparedListener(this);
+```
+
+5 设置 `AVOptions`
+```JAVA
+// Tip: you can custom the variable depending on your situation
+if (mIsLiveStream) {
+ options.setInteger(AVOptions.KEY_BUFFER_TIME, 1000); // the unit of buffer time is ms
+ options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000); // the unit of timeout is ms
+ options.setString(AVOptions.KEY_FFLAGS, AVOptions.VALUE_FFLAGS_NOBUFFER); // "nobuffer"
+ options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
+}
+mAudioPlayer.setAVOptions(options);
+```
## 依赖库
* ffmpeg
@@ -39,8 +220,76 @@ Android 2.3 (API 9) 及其以上
* sdl
* libVLC
-## 反馈及意见
+## 版本历史
+
+### 播放器
+
+* 1.1.6 ([Release Notes][8])
+ - 发布 pldroid-player-1.1.6.jar
+ - 更新 libpldroidplayer.so
+ - 更新 ijkmediaplayer.jar
+ - 新增 `OnVideoSizeChangedListener#onVideoSizeChanged(IMediaPlayer, int, int, int, int)` 回调
+ - 修复概率性无视频有音频的现象
+ - 新增全屏播放 Demo 展示代码
+
+* 1.1.4 ([Release Notes][7])
+ - 发布 pldroid-player-1.1.4.jar
+ - 更新 libpldroidplayer.so
+ - 新增播放器全屏播放支持
+ - 新增纯音频播放 `AVOptions` 支持
+ - 修复播放过程中,概率性异常地回调 `onCompletion` 问题
+ - `VideoView` 布局的展示代码
+
+* 1.1.3 ([Release Notes][6])
+ - 发布 pldroid-player-1.1.3.jar
+ - 更新 libpldroidplayer.so
+ - 新增 armeabi, x86 支持
+ - 新增 `KEY_LIVE_STREAMING` option
+ - 修复 `getCurrentPosition` 和 `getDuration` 返回值异常问题
+ - 修复播放过程中,概率性不间断地回调 onCompletion 问题
+ - 更新不同播放方式(直播或点播)设置 option 的展示代码
+
+* 1.1.2 ([Release Notes][5])
+ - 发布 pldroid-player-1.1.2.jar
+ - 更新 arm64-v8a/libpldroidplayer.so,armeabi-v7a/libpldroidplayer.so
+ - 修复推流端断流后,Player 概率性地无 `onCompletion` 回调通知
+ - 修复 `AVOptions` 的 key 没有设置 value 时候的 Crash 问题
+
+* 1.1.1 ([Release Notes][4])
+ - 发布 pldroid-player-1.1.1.jar
+ - 发布 arm64-v8a/libpldroidplayer.so,增加 arm64 v8a 支持
+ - 更新 arm-v7a 版本的 libpldroidplayer.so
+ - 增加 `AVOptions` 类,可设置如下属性:
+ * `AVOptions.KEY_GET_AV_FRAME_TIMEOUT` // ms
+ * `AVOptions.KEY_MEDIACODEC` // 1 means enable, 0 means disable
+ * `AVOptions.KEY_FFLAGS` // "nobuffer"
+ * `AVOptions.KEY_BUFFER_TIME` // ms
+ - 修复部分音视频流无法播放的问题
+ - 修复仅含视频流无法播放的问题
+ - 优化连接时间
+ - 废除 `setBufferTime(float ms)` 接口,使用 `AVOptions` 代替
+ - 增加 `AVOptions` 的演示代码
+
+* 1.1.0 ([Release Notes][3])
+ - 发布 pldroid-player-1.1.0.jar
+ - 更新 ijkmediaplayer.jar
+ - 更新 libpldroidplayer.so
+ - 添加纯音频播放接口,支持后台运行
+ - 添加 bufferTime 设置接口:`setBufferTime(float ms)`
+ - 添加状态码:`EXTRA_CODE_CONNECTION_REFUSED` 和 `EXTRA_CODE_EOF`
+ - 优化播放延时
+ - 优化播放过程中因断流导致的等待时间
+ - 修复部分机型硬解码异常问题
+ - 添加纯音频播放展示界面
-当你遇到任何问题时,可以通过在 GitHub 的 repo 提交 issues 来反馈问题,请尽可能的描述清楚遇到的问题,如果有错误信息也一同附带,并且在 Labels 中指明类型为 bug 或者其他。
+* 1.0.0 ([Release Notes][2])
+ - 发布 PLDroidPlayer v1.0.0
-[通过这里查看已有的 issues 和提交 Bug](https://github.com/pili-engineering/PLDroidPlayer/issues)。
\ No newline at end of file
+[1]: /PLDroidPlayerDemo
+[2]: /ReleaseNotes/release-notes-1.0.0.md
+[3]: /ReleaseNotes/release-notes-1.1.0.md
+[4]: /ReleaseNotes/release-notes-1.1.1.md
+[5]: /ReleaseNotes/release-notes-1.1.2.md
+[6]: /ReleaseNotes/release-notes-1.1.3.md
+[7]: /ReleaseNotes/release-notes-1.1.4.md
+[8]: /ReleaseNotes/release-notes-1.1.6.md
diff --git a/ReleaseNotes/release-notes-1.2.0.md b/ReleaseNotes/release-notes-1.2.0.md
deleted file mode 100644
index 1b49220..0000000
--- a/ReleaseNotes/release-notes-1.2.0.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# PLDroidPlayer Release Notes for 1.2.0
-
-## 简介
-PLDroidPlayer 为 Android 开发者提供直播播放 SDK
-
-## 记录
-
-### 播放器
- - 发布 pldroid-player-1.2.0.jar
- - 删除了 ijkmediaplayer.jar
- - 实现播放器秒开优化,网络条件好的情况下,可以实现秒开
- - 新增接口类:`PLMediaPlayer`,`PLVideoView`,`PLVideoTextureView`
- - `PLMediaPlayer` 类提供了播放器的核心功能,播放器界面全部由开发者定制
- - 相比于 `VideoView` 类,`PLVideoView` 和 `PLVideoTextureView` 新增了 `setDisplayAspectRatio` 接口,用于配置画面预览模式,包括:原始视频尺寸、适应屏幕、铺满全屏、16:9、4:3 多种预览方式
- - `PLVideoTextureView` 提供 `setDisplayOrientation` 接口,用于配置画面旋转,支持的旋转角度:0度,90度,180度,270度
- - 更新 Demo 程序,演示所有新增的接口类
-
-### 播放器 Demo
-
-- 优化 Demo 程序的框架
-- 新增 `PLMediaPlayerActivity`,用于演示 `PLMediaPlayer` 接口
-- 新增 `PLVideoViewActivity`,用于演示 `PLVideoView` 接口
-- 新增 `PLVideoTextureViewActivity`,用于演示 `PLVideoTextureView` 接口
-- 新增 `PLAudioPlayerActivity`,用于演示使用 `PLMediaPlayer` 接口完成纯音频播放
-
diff --git a/releases/ijkmediaplayer.jar b/releases/ijkmediaplayer.jar
new file mode 100644
index 0000000..3253d75
Binary files /dev/null and b/releases/ijkmediaplayer.jar differ
diff --git a/releases/pldroid-player-1.0.0.jar b/releases/pldroid-player-1.0.0.jar
new file mode 100644
index 0000000..06ae8aa
Binary files /dev/null and b/releases/pldroid-player-1.0.0.jar differ
diff --git a/releases/pldroid-player-1.1.0.jar b/releases/pldroid-player-1.1.0.jar
new file mode 100644
index 0000000..a310cf1
Binary files /dev/null and b/releases/pldroid-player-1.1.0.jar differ
diff --git a/releases/pldroid-player-1.1.1.jar b/releases/pldroid-player-1.1.1.jar
new file mode 100644
index 0000000..3da4583
Binary files /dev/null and b/releases/pldroid-player-1.1.1.jar differ
diff --git a/releases/pldroid-player-1.1.2.jar b/releases/pldroid-player-1.1.2.jar
new file mode 100644
index 0000000..c75d3f2
Binary files /dev/null and b/releases/pldroid-player-1.1.2.jar differ
diff --git a/releases/pldroid-player-1.1.3.jar b/releases/pldroid-player-1.1.3.jar
new file mode 100644
index 0000000..4a3b43e
Binary files /dev/null and b/releases/pldroid-player-1.1.3.jar differ
diff --git a/releases/pldroid-player-1.1.4.jar b/releases/pldroid-player-1.1.4.jar
new file mode 100644
index 0000000..98f401a
Binary files /dev/null and b/releases/pldroid-player-1.1.4.jar differ
diff --git a/releases/pldroid-player-1.1.6.jar b/releases/pldroid-player-1.1.6.jar
new file mode 100644
index 0000000..68e1bb5
Binary files /dev/null and b/releases/pldroid-player-1.1.6.jar differ
diff --git a/releases/pldroid-player-1.2.0.jar b/releases/pldroid-player-1.2.0.jar
deleted file mode 100644
index 474ddb6..0000000
Binary files a/releases/pldroid-player-1.2.0.jar and /dev/null differ