智能电视TV开发---直播视频客户端结构设计和实现

时间:2021-02-05 15:56:33

智能电视TV开发---客户端和服务器通信里面我们实现了客户端和服务端的简单通信,接下来我们做一个简单的客户端界面,来实现手机端来操控智能电视的TV端。

一、存储视频的结构设计

我们在做客户端的时候,通常是需要存储视频的相关信息,结构如下:

package com.jwzhangjie.smarttv_client.model;

import android.os.Parcel;
import android.os.Parcelable; public class LiveModel implements Parcelable{ /**
* 数据库位置
*/
private int db_id;
/**
* 直播频道的id
*/
private int channel_id;
/**
* 直播频道的名称
*/
private String channel_name;
/**
* 直播频道的url
*/
private String icon_url;
/**
* 直播频道的省份
*/
private String province;
/**
* 直播频道清晰度
*/
private String mode;
/**
* 直播频道的链接
*/
private String url;
/**
* 直播频道的second_url
*/
private String second_url;
/**
* 直播频道所属的类型
*/
private String types; public LiveModel(){ }
private LiveModel(Parcel parcel){
readFromParcel(parcel);
}
@Override
public int describeContents() {
return 0;
} public void readFromParcel(Parcel parcel){
db_id = parcel.readInt();
channel_id = parcel.readInt();
channel_name = parcel.readString();
icon_url = parcel.readString();
province = parcel.readString();
mode = parcel.readString();
url = parcel.readString();
second_url = parcel.readString();
types = parcel.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(db_id);
dest.writeInt(channel_id);
dest.writeString(channel_name);
dest.writeString(icon_url);
dest.writeString(province);
dest.writeString(mode);
dest.writeString(url);
dest.writeString(second_url);
dest.writeString(types);
} public static Creator<LiveModel> CREATOR = new Creator<LiveModel>() { @Override
public LiveModel createFromParcel(Parcel source) {
return new LiveModel(source);
} @Override
public LiveModel[] newArray(int size) {
return new LiveModel[size];
}
}; public int getDb_id() {
return db_id;
}
public void setDb_id(int db_id) {
this.db_id = db_id;
}
public int getChannel_id() {
return channel_id;
}
public void setChannel_id(int channel_id) {
this.channel_id = channel_id;
}
public String getChannel_name() {
return channel_name;
}
public void setChannel_name(String channel_name) {
this.channel_name = channel_name;
}
public String getIcon_url() {
return icon_url;
}
public void setIcon_url(String icon_url) {
this.icon_url = icon_url;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getSecond_url() {
return second_url;
}
public void setSecond_url(String second_url) {
this.second_url = second_url;
}
public String getTypes() {
return types;
}
public void setTypes(String types) {
this.types = types;
} }

二、数据库设计

  接下来我们设计数据库表格,代码如下:
package com.jwzhangjie.smarttv_client.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment; public class DBHelper extends SQLiteOpenHelper{ private static final String NAME = "tv_jie.sqlite";
public static final String DB_PATH = Environment.getExternalStorageDirectory() + "/";
private static final int DB_VERSION = 1;
public static final String LIVE_VIDEO="CREATE TABLE live_video " +
"('db_id' INTEGER PRIMARY KEY AUTOINCREMENT, 'channel_id' INTEGER," +
" 'channel_name' VARCHAR, 'icon_url' VARCHAR, 'province' VARCHAR, 'mode' VARCHAR, " +
"'url' VARCHAR, 'second_url' VARCHAR, 'types' VARCHAR)"; public DBHelper(Context context) {
super(context, DB_PATH + NAME, null, DB_VERSION);
} public DBHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(LIVE_VIDEO);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF live_video");
} }

三、调用数据库,首先数据的插入,或直播,获取直播的个数

package com.jwzhangjie.smarttv_client.utils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; import com.jwzhangjie.smarttv_client.db.DBHelper;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; public class DBUtils implements Serializable{ private static final long serialVersionUID = 1L; private static DBHelper mDBHelper; public DBUtils(Context paramContext) {
mDBHelper = new DBHelper(paramContext);
} public void close() {
if (mDBHelper != null) {
mDBHelper.close();
}
} public void insertLiveVideo(LiveVideoModel liveModel){
SQLiteDatabase db = null;
try {
db = mDBHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("channel_id", liveModel.getChannel_id());
contentValues.put("channel_name", liveModel.getChannel_name());
contentValues.put("icon_url", liveModel.getIcon_url());
contentValues.put("province", liveModel.getProvince());
contentValues.put("mode", liveModel.getMode());
contentValues.put("url", liveModel.getUrl());
contentValues.put("second_url", liveModel.getSecond_url());
contentValues.put("types", liveModel.getTypes());
db.insertOrThrow("live_video", null, contentValues);
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取所有的直播视频的个数
* @return
*/
public int getMovieCount() {
SQLiteDatabase db = mDBHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT count(*) FROM live_video", null);
cursor.moveToNext();
int coutn = cursor.getInt(0);
cursor.close();
db.close();
return coutn;
} public List<LiveVideoModel> getLiveVideoModels(){
List<LiveVideoModel> listData = new ArrayList<LiveVideoModel>();
try {
SQLiteDatabase db = mDBHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM live_video", null);
while (cursor.moveToNext()) {
LiveVideoModel mVideoModel = new LiveVideoModel();
mVideoModel.setDb_id(cursor.getInt(0));
mVideoModel.setChannel_id(cursor.getInt(1));
mVideoModel.setChannel_name(cursor.getString(2));
mVideoModel.setIcon_url(cursor.getString(3));
mVideoModel.setProvince(cursor.getString(4));
mVideoModel.setMode(cursor.getString(5));
mVideoModel.setUrl(cursor.getString(6));
mVideoModel.setSecond_url(cursor.getString(7));
mVideoModel.setTypes(cursor.getString(8));
listData.add(mVideoModel);
}
} catch (Exception e) {
e.printStackTrace();
}
return listData;
} }

具体的数据自己去填充,这里我就不提供了,各大视频论坛都分享

四、客户端视频数据的显示

  这里已经假设数据库已经有数据了,界面很简单就是一个listView来显示,自定义一个adapter

4.1ListView中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:orientation="horizontal" >
<ImageView
android:id="@+id/item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:layout_centerVertical="true"
android:src="@drawable/widget_progress_medium_rotation_image"
android:contentDescription="@string/app_name"
/>
<ImageView
android:id="@+id/arrow_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/arrow_right"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dip"
android:contentDescription="@string/app_name"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/item_icon"
android:layout_toLeftOf="@id/arrow_right"
android:orientation="vertical"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:layout_marginLeft="10dip"
>
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="title"
/>
<TextView
android:id="@+id/item_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="subtitle"
/>
</LinearLayout>
</RelativeLayout>

4.2网络图片加载方式

这里涉及的直播频道的图标都是网络图片,所以要实现加载网络图片的功能,这里我使用的是网络一个开源的库com.nostra13.universalimageloader,在网上一搜就能看见,所以要使用它我们要配置一些内容。

首先编写一个类继承Application,然后再AndroidManifest.xml里面设置Application的name属性,代码如下:
package com.jwzhangjie.smarttv_client.utils;

import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import android.app.Application;
import android.content.Context; public class SmartTV_App extends Application { @Override
public void onCreate() {
super.onCreate();
initImageLoader(getApplicationContext());
} public static void initImageLoader(Context context) {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs() // Remove for release app
.build();
ImageLoader.getInstance().init(config);
}
}

4.3ListView的adapter设计

package com.jwzhangjie.smarttv_client.adapter;

import java.util.List;

import com.jwzhangjie.smarttv_client.R;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader; import android.content.Context;
import android.graphics.Bitmap;
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 LiveVideoAdapter extends BaseAdapter{ private LayoutInflater mInflater;
private List<LiveVideoModel> listDatas;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions options;
public LiveVideoAdapter(Context context){
mInflater = LayoutInflater.from(context);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.img_loading_bg)
.showImageForEmptyUri(R.drawable.img_loading_empty)
.showImageOnFail(R.drawable.img_loading_error)
.cacheInMemory(true)
.cacheOnDisc(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
} public void updateListDatas(List<LiveVideoModel> listDatas){
this.listDatas = listDatas;
notifyDataSetChanged();
}
@Override
public int getCount() {
return listDatas == null ?0:listDatas.size();
} @Override
public Object getItem(int position) {
return listDatas.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_live, null);
viewHolder.item_icon = (ImageView)convertView.findViewById(R.id.item_icon);
viewHolder.item_arrow = (ImageView)convertView.findViewById(R.id.arrow_right);
viewHolder.item_title = (TextView)convertView.findViewById(R.id.item_title);
viewHolder.item_subtitle = (TextView)convertView.findViewById(R.id.item_subtitle);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder)convertView.getTag();
}
LiveVideoModel videoModel = listDatas.get(position);
viewHolder.item_title.setText(videoModel.getChannel_name());
viewHolder.item_subtitle.setText("省份:"+videoModel.getProvince());
imageLoader.displayImage(videoModel.getIcon_url(), viewHolder.item_icon, options);
return convertView;
} class ViewHolder{
private ImageView item_icon;
private ImageView item_arrow;
private TextView item_title;
private TextView item_subtitle;
} }

4.4主界面布局设计

<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=".Smart_TV_Client" > <RelativeLayout
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="60dip"
android:background="#d0d0d0"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="直播界面测试"
android:layout_centerInParent="true"
android:textSize="16sp"
android:textStyle="bold"
/>
</RelativeLayout>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/title"
android:cacheColorHint="#00000000"
android:divider="@drawable/cbox_uc_divider"
android:fadeScrollbars="false"
android:fastScrollEnabled="false"
android:focusable="true"
android:focusableInTouchMode="true"
android:scrollbars="none"
android:scrollingCache="false"
></ListView>
</RelativeLayout>

4.5 主界面代码编写

这里就是这章最后的一步,调用数据库数据,然后传值给adapter,显示在listview上面
package com.jwzhangjie.smarttv_client;

import java.util.List;

import com.jwzhangjie.smarttv_client.adapter.LiveVideoAdapter;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel;
import com.jwzhangjie.smarttv_client.utils.DBUtils; import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.Window;
import android.widget.ListView; public class Smart_TV_Client extends Activity { private ListView listView;
private LiveVideoAdapter adapter;
private DBUtils dbUtils;
private List<LiveVideoModel> listDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smart__tv__client);
dbUtils = new DBUtils(this);
initView();
loadData();
} public void initView(){
adapter = new LiveVideoAdapter(this);
listView = (ListView)findViewById(R.id.listview);
listView.setAdapter(adapter);
} public void loadData(){
new loadData().execute();
} private class loadData extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
listDatas = dbUtils.getLiveVideoModels();
return null;
} @Override
protected void onPostExecute(Void result) {
adapter.updateListDatas(listDatas);
super.onPostExecute(result);
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.smart__tv__client, menu);
return true;
} }

5.显示效果

智能电视TV开发---直播视频客户端结构设计和实现