Java tutorial
/* * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.figo.mydemo.ui.activity; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.BackgroundColorSpan; import android.text.style.ImageSpan; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TableLayout; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import cn.figo.mydemo.R; import cn.figo.mydemo.app.Settings; import cn.figo.mydemo.content.RecentMediaStorage; import cn.figo.mydemo.ui.fragment.TracksFragment; import cn.figo.mydemo.widget.media.AndroidMediaController; import cn.figo.mydemo.widget.media.IjkVideoView; import cn.figo.mydemo.widget.media.MeasureHelper; import master.flame.danmaku.controller.IDanmakuView; import master.flame.danmaku.danmaku.loader.ILoader; import master.flame.danmaku.danmaku.loader.IllegalDataException; import master.flame.danmaku.danmaku.loader.android.DanmakuLoaderFactory; import master.flame.danmaku.danmaku.model.BaseDanmaku; import master.flame.danmaku.danmaku.model.DanmakuTimer; import master.flame.danmaku.danmaku.model.IDanmakus; import master.flame.danmaku.danmaku.model.IDisplayer; import master.flame.danmaku.danmaku.model.android.BaseCacheStuffer; import master.flame.danmaku.danmaku.model.android.DanmakuContext; import master.flame.danmaku.danmaku.model.android.Danmakus; import master.flame.danmaku.danmaku.model.android.SpannedCacheStuffer; import master.flame.danmaku.danmaku.parser.BaseDanmakuParser; import master.flame.danmaku.danmaku.parser.IDataSource; import master.flame.danmaku.danmaku.parser.android.BiliDanmukuParser; import master.flame.danmaku.danmaku.util.IOUtils; import tv.danmaku.ijk.media.player.IjkMediaPlayer; import tv.danmaku.ijk.media.player.misc.ITrackInfo; public class VideoActivity extends AppCompatActivity implements TracksFragment.ITrackHolder { private static final String TAG = "VideoActivity"; private String mVideoPath; private Uri mVideoUri; private AndroidMediaController mMediaController; private IjkVideoView mVideoView; private TextView mToastTextView; private TableLayout mHudView; private DrawerLayout mDrawerLayout; private ViewGroup mRightDrawer; private Settings mSettings; private boolean mBackPressed; public static Intent newIntent(Context context, String videoPath, String videoTitle) { Intent intent = new Intent(context, VideoActivity.class); intent.putExtra("videoPath", videoPath); intent.putExtra("videoTitle", videoTitle); return intent; } public static void intentTo(Context context, String videoPath, String videoTitle) { context.startActivity(newIntent(context, videoPath, videoTitle)); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); mSettings = new Settings(this); // handle arguments mVideoPath = getIntent().getStringExtra("videoPath"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { String scheme = mVideoUri.getScheme(); if (TextUtils.isEmpty(scheme)) { Log.e(TAG, "Null unknown ccheme\n"); finish(); return; } if (scheme.equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) { mVideoPath = mVideoUri.getPath(); } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { Log.e(TAG, "Can not resolve content below Android-ICS\n"); finish(); return; } else { Log.e(TAG, "Unknown scheme " + scheme + "\n"); finish(); return; } } Intent intent = getIntent(); String intentAction = intent.getAction(); if (!TextUtils.isEmpty(intentAction)) { if (intentAction.equals(Intent.ACTION_VIEW)) { mVideoPath = intent.getDataString(); } else if (intentAction.equals(Intent.ACTION_SEND)) { mVideoUri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { String scheme = mVideoUri.getScheme(); if (TextUtils.isEmpty(scheme)) { Log.e(TAG, "Null unknown ccheme\n"); finish(); return; } if (scheme.equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) { mVideoPath = mVideoUri.getPath(); } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { Log.e(TAG, "Can not resolve content below Android-ICS\n"); finish(); return; } else { Log.e(TAG, "Unknown scheme " + scheme + "\n"); finish(); return; } } } } if (!TextUtils.isEmpty(mVideoPath)) { new RecentMediaStorage(this).saveUrlAsync(mVideoPath); } // init UI Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); mMediaController = new AndroidMediaController(this, false); mMediaController.setSupportActionBar(actionBar); mToastTextView = (TextView) findViewById(R.id.toast_text_view); mHudView = (TableLayout) findViewById(R.id.hud_view); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mRightDrawer = (ViewGroup) findViewById(R.id.right_drawer); mDrawerLayout.setScrimColor(Color.TRANSPARENT); new RecentMediaStorage(this).saveUrlAsync(mVideoPath); // init player IjkMediaPlayer.loadLibrariesOnce(null); IjkMediaPlayer.native_profileBegin("libijkplayer.so"); mVideoView = (IjkVideoView) findViewById(R.id.video_view); mVideoView.setMediaController(mMediaController); mVideoView.setHudView(mHudView); mVideoView.toggleAspectRatio(); if (mVideoPath != null) mVideoView.setVideoPath(mVideoPath); else if (mVideoUri != null) mVideoView.setVideoURI(mVideoUri); else { Log.e(TAG, "Null Data Source\n"); finish(); return; } initDanmaku(); } public void initDanmaku() { // HashMap<Integer, Integer> maxLinesPair = new HashMap<Integer, Integer>(); maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 3 // ???? HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<Integer, Boolean>(); overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true); overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true); mDanmakuView = (IDanmakuView) findViewById(R.id.sv_danmaku); danmakuContext = DanmakuContext.create(); danmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3).setDuplicateMergingEnabled(false) .setScrollSpeedFactor(1.2f).setScaleTextSize(1.2f) .setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // SpannedCacheStuffer // .setCacheStuffer(new BackgroundCacheStuffer()) // BackgroundCacheStuffer .setMaximumLines(maxLinesPair).preventOverlapping(overlappingEnablePair); if (mDanmakuView != null) { mParser = createParser(getResources().openRawResource(R.raw.comments)); mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() { @Override public void updateTimer(DanmakuTimer timer) { } @Override public void drawingFinished() { } @Override public void danmakuShown(BaseDanmaku danmaku) { // Log.d("DFM", "danmakuShown(): text=" + danmaku.text); } @Override public void prepared() { mDanmakuView.start(); } }); // mDanmakuView.setOnDanmakuClickListener(new IDanmakuView.OnDanmakuClickListener() { // @Override // public void onDanmakuClick(BaseDanmaku latest) { // Log.d("DFM", "onDanmakuClick text:" + latest.text); // mMediaController.setVisibility(View.VISIBLE); // mVideoView.performClick(); // } // // @Override // public void onDanmakuClick(IDanmakus danmakus) { // Log.d("DFM", "onDanmakuClick danmakus size:" + danmakus.size()); // mMediaController.setVisibility(View.VISIBLE); // } // }); mDanmakuView.prepare(mParser, danmakuContext); mDanmakuView.showFPS(false); mDanmakuView.enableDanmakuDrawingCache(true); // ((View) mDanmakuView).setOnClickListener(new View.OnClickListener() { // // @Override // public void onClick(View view) { // mMediaController.setVisibility(View.VISIBLE); // } // }); } mVideoView.start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_player, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_toggle_ratio) { int aspectRatio = mVideoView.toggleAspectRatio(); String aspectRatioText = MeasureHelper.getAspectRatioText(this, aspectRatio); mToastTextView.setText(aspectRatioText); mMediaController.showOnce(mToastTextView); return true; } else if (id == R.id.action_toggle_player) { int player = mVideoView.togglePlayer(); String playerText = IjkVideoView.getPlayerText(this, player); mToastTextView.setText(playerText); mMediaController.showOnce(mToastTextView); return true; } else if (id == R.id.action_toggle_render) { int render = mVideoView.toggleRender(); String renderText = IjkVideoView.getRenderText(this, render); mToastTextView.setText(renderText); mMediaController.showOnce(mToastTextView); return true; } else if (id == R.id.action_show_info) { mVideoView.showMediaInfo(); } else if (id == R.id.action_show_tracks) { if (mDrawerLayout.isDrawerOpen(mRightDrawer)) { Fragment f = getSupportFragmentManager().findFragmentById(R.id.right_drawer); if (f != null) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.remove(f); transaction.commit(); } mDrawerLayout.closeDrawer(mRightDrawer); } else { Fragment f = TracksFragment.newInstance(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.right_drawer, f); transaction.commit(); mDrawerLayout.openDrawer(mRightDrawer); } } return super.onOptionsItemSelected(item); } @Override public ITrackInfo[] getTrackInfo() { if (mVideoView == null) return null; return mVideoView.getTrackInfo(); } @Override public void selectTrack(int stream) { mVideoView.selectTrack(stream); } @Override public void deselectTrack(int stream) { mVideoView.deselectTrack(stream); } @Override public int getSelectedTrack(int trackType) { if (mVideoView == null) return -1; return mVideoView.getSelectedTrack(trackType); } @Override public void onBackPressed() { mBackPressed = true; super.onBackPressed(); } @Override protected void onStop() { super.onStop(); if (mBackPressed || !mVideoView.isBackgroundPlayEnabled()) { mVideoView.stopPlayback(); mVideoView.release(true); mVideoView.stopBackgroundPlay(); } else { mVideoView.enterBackground(); } IjkMediaPlayer.native_profileEnd(); } //Dannmaku private BaseDanmakuParser mParser; private DanmakuContext danmakuContext; private IDanmakuView mDanmakuView; private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() { private Drawable mDrawable; @Override public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) { if (danmaku.text instanceof Spanned) { // ????? // FIXME ????url new Thread() { @Override public void run() { String url = "http://www.bilibili.com/favicon.ico"; InputStream inputStream = null; Drawable drawable = mDrawable; if (drawable == null) { try { URLConnection urlConnection = new URL(url).openConnection(); inputStream = urlConnection.getInputStream(); drawable = BitmapDrawable.createFromStream(inputStream, "bitmap"); mDrawable = drawable; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(inputStream); } } if (drawable != null) { drawable.setBounds(0, 0, 100, 100); SpannableStringBuilder spannable = createSpannable(drawable); danmaku.text = spannable; if (mDanmakuView != null) { mDanmakuView.invalidateDanmaku(danmaku, false); } return; } } }.start(); } } @Override public void releaseResource(BaseDanmaku danmaku) { // TODO ??:??ImageSpantext?? drawable } }; private BaseDanmakuParser createParser(InputStream stream) { if (stream == null) { return new BaseDanmakuParser() { @Override protected Danmakus parse() { return new Danmakus(); } }; } ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI); try { loader.load(stream); } catch (IllegalDataException e) { e.printStackTrace(); } BaseDanmakuParser parser = new BiliDanmukuParser(); IDataSource<?> dataSource = loader.getDataSource(); parser.load(dataSource); return parser; } private void addDanmaku(boolean islive) { BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL); if (danmaku == null || mDanmakuView == null) { return; } // for(int i=0;i<100;i++){ // } danmaku.text = "?" + System.nanoTime(); danmaku.padding = 5; danmaku.priority = 0; // ????? danmaku.isLive = islive; danmaku.time = mDanmakuView.getCurrentTime() + 1200; danmaku.textSize = 25f * (mParser.getDisplayer().getDensity() - 0.6f); danmaku.textColor = Color.RED; danmaku.textShadowColor = Color.WHITE; // danmaku.underlineColor = Color.GREEN; danmaku.borderColor = Color.GREEN; mDanmakuView.addDanmaku(danmaku); } private void addDanmaKuShowTextAndImage(boolean islive) { BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL); Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher); drawable.setBounds(0, 0, 100, 100); SpannableStringBuilder spannable = createSpannable(drawable); danmaku.text = spannable; danmaku.padding = 5; danmaku.priority = 1; // , ?? danmaku.isLive = islive; danmaku.time = mDanmakuView.getCurrentTime() + 1200; danmaku.textSize = 25f * (mParser.getDisplayer().getDensity() - 0.6f); danmaku.textColor = Color.RED; danmaku.textShadowColor = 0; // ??????(textShadowColor=0)????? danmaku.underlineColor = Color.GREEN; mDanmakuView.addDanmaku(danmaku); } private SpannableStringBuilder createSpannable(Drawable drawable) { String text = "bitmap"; SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text); ImageSpan span = new ImageSpan(drawable);//ImageSpan.ALIGN_BOTTOM); spannableStringBuilder.setSpan(span, 0, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); spannableStringBuilder.append(""); spannableStringBuilder.setSpan(new BackgroundColorSpan(Color.parseColor("#8A2233B1")), 0, spannableStringBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); return spannableStringBuilder; } }