类似的软件已经很多了,并且做的也不错。这个demo主要是为了记录安卓GridView的使用方法。
效果图:
视频播放界面:
-
电视直播m3u8链接的获取
主要就是抓包。在百度搜电视直播,点进一个电视台在线观看,F12查看它的网页源码,找到类似于*.m3u8这样的链接,查看Request URL,这个就是我们需要的播放地址,如下图:
由于这些链接随时可能会失效,我就不贴上来了。这里附上北邮ivi测试列表,里面是高清直播,所以播放会有些卡顿。
-
GridView的使用
GridView使用方法同ListView。
1.在activity_main.xml布局文件里放一个GridView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.tv.MainActivity" >
<GridView
android:id="@+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3">
</GridView>
</RelativeLayout>
2.在item.xml布局文件里设置每一个item的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5sp"
android:layout_marginRight="5sp" >
<ImageView
android:id="@+id/item_imageView"
android:layout_width="100sp"
android:layout_height="80sp"
android:layout_centerHorizontal="true"
android:scaleType="fitCenter"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/item_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item_imageView"
android:layout_centerHorizontal="true"
android:text="北京卫视"
android:textAlignment="center"
android:textColor="#000" />
</RelativeLayout>
3.编写javabean
package com.example.tv;
public class TVItem {
String title;
String image;
String url;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
4.编写适配器代码
我把直播的链接放在了values下的array.xml文件里,主要有三个节点,结构如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="title">
<item>香港卫视</item>
</string-array>
<string-array name="logo">
<item>hkstv</item>
</string-array>
<string-array name="url">
<item>http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8</item>
</string-array>
</resources>
title是显示的名称,logo是放在drawable目录下的图片的名称(不带扩展名),url是直播的链接地址
VideoItemAdapter.java
package com.example.tv;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class VideoItemAdapter extends BaseAdapter {
List<TVItem> list;
Context context;
LayoutInflater inflater;
Handler handler;
public VideoItemAdapter(Context context, Handler handler) {
this.handler = handler;// handler根据需要来传,这里没有用到
this.context = context;
inflater = LayoutInflater.from(context);
getTvItems();
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private void getTvItems() {
list = new ArrayList<TVItem>();
Resources resources = context.getResources();
String[] title = resources.getStringArray(R.array.title);
String[] url = resources.getStringArray(R.array.url);
String[] logo = resources.getStringArray(R.array.logo);
for (int i = 0; i < title.length; i++) {
TVItem tvItem = new TVItem();
tvItem.setTitle(title[i]);
tvItem.setUrl(url[i]);
tvItem.setImage(logo[i]);
list.add(tvItem);
}
}
// 重写getView方法,即设置GridView每一项的视图
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.main_item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);// 设置tag
} else {
holder = (ViewHolder) convertView.getTag(); // 获取tag
}
holder.name.setText(list.get(position).getTitle());
//根据图片名称动态获取资源ID
int resId = context.getResources().getIdentifier(list.get(position).getImage(), "drawable",
context.getPackageName());
holder.thumbnail.setImageResource(resId);
return convertView;
}
// 用于暂时保存视图对象
class ViewHolder {
public TextView name;
public ImageView thumbnail;
public ViewHolder(View view) {
name = (TextView) view.findViewById(R.id.item_textView);
thumbnail = (ImageView) view.findViewById(R.id.item_imageView);
}
}
}
5.在MainActivity设置适配器,监听item点击事件
package com.example.tv;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.Toast;
public class MainActivity extends Activity {
private GridView lv_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_main = findViewById(R.id.lv_main);
lv_main.setAdapter(new VideoItemAdapter(MainActivity.this, null));
lv_main.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO 自动生成的方法存根
TVItem item = (TVItem) parent.getItemAtPosition(position);
Intent intent = new Intent(MainActivity.this, VideoActivity.class);
intent.setData(Uri.parse(item.getUrl()));
startActivity(intent);
}
});
}
}
上面的步骤完成后,点击MainActivity里的电视台,会跳转到VideoActivity进行播放。这里我用的视频播放器不是安卓原生的mediaplayer,而是开源项目PLDroidPlayer,这个用起来比较简单,只要将jar包、so库导入到项目即可(如果用PLVideoView还要有MediaController.java),具体使用方法请百度。
VideoActivity.java
package com.example.tv;
import com.pili.pldroid.player.widget.PLVideoView;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
public class VideoActivity extends Activity {
private PLVideoView plVideoview;
@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_video);
Uri uri = getIntent().getData();
plVideoview = findViewById(R.id.plVideoview);
plVideoview.setVideoURI(uri);
plVideoview.setMediaController(new MediaController(VideoActivity.this));
// 设置全屏播放
plVideoview.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_PAVED_PARENT);
plVideoview.start();
}
@Override
protected void onPause() {
// TODO 自动生成的方法存根
plVideoview.pause();
super.onPause();
}
}
activity_video.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
tools:context="com.example.tv.VideoActivity"
android:keepScreenOn="true" >
<com.pili.pldroid.player.widget.PLVideoView
android:id="@+id/plVideoview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.pili.pldroid.player.widget.PLVideoView>
</RelativeLayout>
最后别忘了在清单文件添加权限
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tv"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".VideoActivity"
android:label="@string/title_activity_video"
android:screenOrientation="landscape" >
</activity>
</application>
</manifest>