1. 程式人生 > >安卓筆記(視訊播放器)

安卓筆記(視訊播放器)

利用Android Studio進行簡單的視訊播放應用(是一個橫向播放的視訊播放器)

因為剛開始學,只會一些簡單的控制元件,可見上圖我只用了五個控制元件,可見是一個十分容易上手的例項。

清楚控制元件後,對於控制元件的佈局,我選擇的是FrameLayout佈局,這是我所用的佈局介面

 首先是對控制元件的名稱分別新增ID,十分重要

然後對安卓上方的標題欄進行隱藏,否則影響整體的外觀樣式,

在res/values/styles檔案中新增:

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

並在Androidmanifest中將theme更改為:

android:theme="@style/AppTheme.NoActionBar">

播放器的View控制元件單獨存在於FrameLayout 佈局下,而播放器的下方的功能欄則單獨存在於LinearLayout佈局中間的控制元件的padding以及background等設定需要自己調整

以上做完後,算是把框架搭好了,接下來是對控制元件的引用,以及許可權的宣告

首先講一下外部呼叫的Androidmanifest許可權宣告,只需在activity新增:

            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="video/*"/>

並在onCreate中接受呼叫

由於程式碼功能過於繁瑣,我先將兩個主要的函式列出,其中播放器的播放拖拽控制,暫停播放的轉換,外部呼叫(你開啟一個視訊可以用該軟體),全屏顯示,控制板的隱藏,新增外部視訊的這些功能,我決定分開來寫。

先是Main函式

public class MainActivity extends AppCompatActivity {

    final String TAG = "測試PlayerActivity";
    final int REQ_OPEN_FILE = 101;

    VideoView videoView;//提出播放器控制元件
    SeekBar seekBar;//可拖放控制元件
    View controlBar;//可播放的面板

    Handler msgHandler;
    Timer timer;
    TimerTask timerTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//隱藏標題
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);//設定全屏
        setContentView(R.layout.activity_main);

        //許可權申請
        Permissions.check(this);

        //初始化介面
        videoView = (VideoView)findViewById(R.id.id_videoView);
        seekBar = (SeekBar)findViewById(R.id.id_seekBar);
        seekBar.setMax(100);


        //訊息支援(可以寫成內部類,用內部類的話onCreate也點長)
        msgHandler = new MyHandler();

        //播放設定(暫停,繼承)
        final ImageButton imageButton = (ImageButton)findViewById(R.id.id_play_pause);
        imageButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view) {
                //此處可優化(事先將兩個圖示載入好,不再每次現載入)
                if (videoView.isPlaying())
                {
                    Log.d(TAG,"正在播放,現在暫停。。。");
                    videoView.pause();
                    imageButton.setImageDrawable(getDrawable(R.drawable.ic_play));
                }
                else
                {
                    Log.d(TAG,"不再播放,現在繼續。。。");
                    videoView.start();
                    imageButton.setImageDrawable(getDrawable(R.drawable.ic_pause));
                }
            }
        });

        //播放控制(進度拖放)
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
        {

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,  boolean fromUser) {
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar)
            {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar)
            {
                //控制視訊到跳轉位置
                if (videoView.isPlaying())
                {
                    int progress = seekBar.getProgress();
                    int position = progress * videoView.getDuration()/100;
                    videoView.seekTo(position);
                }
            }

        });


        //控制面板得顯示和隱藏
        controlBar = findViewById(R.id.id_contral_Bar);
        videoView.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Log.d(TAG,"點中畫畫..");
                if(controlBar.getVisibility() == View.GONE)
                {
                    controlBar.setVisibility(View.VISIBLE);
                    Log.d(TAG,"顯示播放控制面板..");
                }
                else
                {
                    controlBar.setVisibility(View.GONE);
                    Log.d(TAG,"隱藏播放控制面板..");
                }
                return false;
            }
        });


        //接受外部呼叫
        Intent intent = getIntent();
        Uri mediaUri = intent.getData();
        if (mediaUri != null)
        {
            videoView.setVideoURI(mediaUri);
            videoView.start();
        }

    }

    @Override
    protected void onStart() {
        if (getRequestedOrientation()!= ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
        {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

        super.onStart();

        if (timer == null)
        {
            //啟動定時器(間隔500ms)
            timerTask = new MyTimeTask();
            timer = new Timer();
            timer.schedule(timerTask,500,500);
        }

    }

    @Override
    protected void onStop() {
        super.onStop();

        if (timer != null)
        {
            //本介面已經隱藏,要停止定時器(因為本介面已經隱藏,如果繼續重新整理將毫無意義,白白耗費CPU)
            timer.cancel();
            timer = null;
        }
        super.onStop();
    }

    //點選“按鈕”
    public void openFile(View view)
    {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("video/*");
        startActivityForResult(intent,REQ_OPEN_FILE);
    }



    //從媒體管理器返回
    protected void onActivityResult(int requestCode,int resultCode,Intent data)
    {
        if (requestCode == REQ_OPEN_FILE)
        {
            if (resultCode == RESULT_OK)
            {
                Uri mediaUri = data.getData();
                videoView.setVideoURI(mediaUri);
                videoView.start();
            }
        }
    }

    //當視訊停止時,
    //  更新顯示進度:duration總時長,position 當前播放位置
    public void showProgess(int duration,int position)
    {
        //轉化百分比
        int percent =  position * 100 / duration;
        seekBar.setProgress(percent);
    }


    ////////////////訊息支援/////////////////
    private class MyHandler extends Handler
    {

        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1)
            {
                //從訊息裡取出進度資料,然後更新UI
                int duration = msg.arg1;
                int position = msg.arg2;
                showProgess(duration,position);
            }
            super.handleMessage(msg);
        }
    }

    ////////////////定時器的任務////////////////////
    private class MyTimeTask extends TimerTask
    {
        @Override
        public void run() {
            //如果當前VideoView並不在播放中,就不在做什麼
            if (!videoView.isPlaying())return;

            //取得當前播放進度
            int duration = videoView.getDuration();//單位 毫秒(ms)
            int position = videoView.getCurrentPosition();//單位 毫秒(ms)
            //在工作執行緒不能直接更新UI,必須發訊息給UI執行緒,然後再Handler裡處理

            //發執行緒給UI執行緒
            Message msg = new Message();
            msg.what = 1;//訊息型別
            msg.arg1 = duration;//-
            msg.arg2 = position;
            msgHandler.sendMessage(msg);
        }
    }
}

然後是Permissions檔案

public class Permissions
{
    // 檢查和申請許可權
    static final int PERMISSION_REQ_CODE = 1;
    public static void check(Activity activity)
    {
        // 要申請的許可權列表
        final String[] permissions = {
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.INTERNET,
                Manifest.permission.CAMERA
        };

        // 檢查本應用是否有了 WRITE_EXTERNAL_STORAGE 許可權
        if (ContextCompat.checkSelfPermission(activity, permissions[0])
                != PackageManager.PERMISSION_GRANTED)
        {
            // 系統將彈出一個對話方塊,詢問使用者是否授權
            ActivityCompat.requestPermissions(activity, permissions, PERMISSION_REQ_CODE);
        }
    }
}

以上就是組成播放器的主要程式碼

寫的不好請指正。