<!DOCTYPE html>
	<html lang="vi" xmlns="http://www.w3.org/1999/xhtml" prefix="og: http://ogp.me/ns#">
	<head>
<title>Lập trình android cho tivi</title>
<meta name="description" content="Lập trình android cho tivi - Savefile - Tin Tức - http&#x3A;&#x002F;&#x002F;phanmemthienha.com&#x002F;news&#x002F;savefile&#x002F;huong-dan-phan-mem&#x002F;lap-trinh-android-cho-tivi-220.html">
<meta name="author" content="PHAN MEM THIEN HA">
<meta name="copyright" content="PHAN MEM THIEN HA [phamhuy842005@gmail.com]">
<meta name="robots" content="index, archive, follow, noodp">
<meta name="googlebot" content="index,archive,follow,noodp">
<meta name="msnbot" content="all,index,follow">
<meta name="generator" content="NukeViet v4.0">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta property="og:title" content="Lập trình android cho tivi">
<meta property="og:type" content="website">
<meta property="og:description" content="Savefile - Tin Tức - http&#x3A;&#x002F;&#x002F;phanmemthienha.com&#x002F;news&#x002F;savefile&#x002F;huong-dan-phan-mem&#x002F;lap-trinh-android-cho-tivi-220.html">
<meta property="og:site_name" content="PHAN MEM THIEN HA">
<meta property="og:url" content="http://phanmemthienha.com/news/huong-dan-phan-mem/lap-trinh-android-cho-tivi-220.html">
<link rel="shortcut icon" href="http://phanmemthienha.com/uploads/logo-shop-thien-ha-5.png">
<link rel="canonical" href="http://phanmemthienha.com/news/huong-dan-phan-mem/lap-trinh-android-cho-tivi-220.html">
<link rel="alternate" href="http://phanmemthienha.com/news/rss/" title="Tin Tức" type="application/rss+xml">
<link rel="alternate" href="http://phanmemthienha.com/news/rss/huong-dan-phan-mem/" title="Tin Tức - Hướng dẫn phần mềm" type="application/rss+xml">
<link rel="alternate" href="http://phanmemthienha.com/news/rss/huong-dan-noi-bo/" title="Tin Tức - Hướng dẫn nội bộ" type="application/rss+xml">
<link rel="alternate" href="http://phanmemthienha.com/news/rss/Doi-tac/" title="Tin Tức - Đối tác" type="application/rss+xml">
<link rel="alternate" href="http://phanmemthienha.com/news/rss/Tuyen-dung/" title="Tin Tức - Tuyển dụng" type="application/rss+xml">
<link rel="preload" as="script" href="http://phanmemthienha.com/assets/js/jquery/jquery.min.js">
<link rel="preload" as="script" href="http://phanmemthienha.com/assets/js/language/vi.js">
<link rel="preload" as="script" href="http://phanmemthienha.com/assets/js/global.js">
<link rel="preload" as="script" href="http://phanmemthienha.com/themes/default/js/news.js">
<link rel="preload" as="script" href="http://phanmemthienha.com/themes/popovleather/js/main.js">
<link rel="preload" as="script" href="http://phanmemthienha.com/themes/popovleather/js/bootstrap.min.js">
<link rel="StyleSheet" href="http://phanmemthienha.com/assets/css/font-awesome.min.css">
<link rel="StyleSheet" href="http://phanmemthienha.com/themes/popovleather/css/bootstrap.min.css">
<link rel="StyleSheet" href="http://phanmemthienha.com/themes/popovleather/css/style.css">
<link rel="StyleSheet" href="http://phanmemthienha.com/themes/popovleather/css/style.responsive.css">
<link rel="StyleSheet" href="http://phanmemthienha.com/themes/default/css/news.css">
<link rel="StyleSheet" href="http://phanmemthienha.com/assets/css/popovleather.vi.0.css?t=87">
<style>
	body{background: #fff;}
</style>
	</head>
	<body>
<div id="print">
	<div id="hd_print">
		<h2 class="pull-left">PHAN MEM THIEN HA</h2>
		<p class="pull-right"><a title="PHAN MEM THIEN HA" href="http://phanmemthienha.com/">http://phanmemthienha.com</a></p>
	</div>
	<div class="clear"></div>
	<hr />
	<div id="content">
		<h1>Lập trình android cho tivi</h1>
		<ul class="list-inline">
			<li>Thứ tư - 06/11/2024 15:41</li>
			<li class="hidden-print txtrequired"><em class="fa fa-print">&nbsp;</em><a title="In ra" href="javascript:;" onclick="window.print()">In ra</a></li>
			<li class="hidden-print txtrequired"><em class="fa fa-power-off">&nbsp;</em><a title="Đóng cửa sổ này" href="javascript:;" onclick="window.close()">Đóng cửa sổ này</a></li>
		</ul>
		<div class="clear"></div>
		<div id="hometext">
			Hướng dẫn lập trình ứng dụng Android bằng Kotlin để phát video từ cơ sở dữ liệu MySQL thông qua một máy chủ web PHP. Ứng dụng sẽ hiển thị danh sách các chủ đề (topic) và danh sách video (clip) thuộc các chủ đề đó, sau đó phát video được chọn
		</div>
				<div class="imghome">
			<img alt="Lập trình android cho tivi" src="http://phanmemthienha.com/uploads/news/2024_11/image-20241106155957-1.png" width="460" class="img-thumbnail" />
		</div>
		<div class="clear"></div>
		<div id="bodytext" class="clearfix">
			Hướng dẫn lập trình ứng dụng Android bằng Kotlin để phát video từ cơ sở dữ liệu MySQL thông qua một máy chủ web PHP. Ứng dụng sẽ hiển thị danh sách các chủ đề (topic) và danh sách video (clip) thuộc các chủ đề đó, sau đó phát video được chọn<img alt="" height="276" src="http://phanmemthienha.com/uploads/news/2024_11/image-20241106155957-1.png" width="1719" />
<h3>Phân tích cấu trúc bảng</h3>

<p>Dựa trên cấu trúc hai bảng bạn đã cung cấp:</p>

<ol>
	<li><strong>Bảng <code>videoclips_topic</code></strong>: Chứa thông tin về các chủ đề video.</li>
	<li><strong>Bảng <code>videoclips_clip</code></strong>: Chứa thông tin về các video clip, bao gồm đường dẫn tới file video.</li>
</ol>

<h3>Các bước thực hiện</h3>

<h4>Bước 1: Tạo API trên PHP để lấy dữ liệu</h4>

<p>Như đã đề cập trước đó, bạn cần tạo các API PHP để lấy dữ liệu chủ đề và video dưới dạng JSON. Chi tiết API có thể tham khảo lại ở phần trước.<br  />
1.1 API PHP - Lấy danh sách chủ đề</p>

<p>API này sẽ trả về danh sách chủ đề (<code>videoclips_topic</code>).</p>

<p>&nbsp;</p>

<pre>
<code>&lt;?php
header(&#039;Content-Type: application/json&#039;);
$servername = &quot;localhost&quot;;
$username = &quot;root&quot;;
$password = &quot;&quot;;
$dbname = &quot;your_database_name&quot;; // Thay bằng tên cơ sở dữ liệu của bạn

$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn-&gt;connect_error) {
    die(&quot;Connection failed: &quot; . $conn-&gt;connect_error);
}

$sql = &quot;SELECT * FROM nv4_vi_videoclips_topic WHERE status = 1&quot;; // Chú ý thay nv4_vi_videoclips_topic cho đúng nhé.
$result = $conn-&gt;query($sql);

$topics = &#91;&#93;;
if ($result-&gt;num_rows &gt; 0) {
    while($row = $result-&gt;fetch_assoc()) {
        $topics&#91;&#93; = $row;
    }
}

echo json_encode($topics);
$conn-&gt;close();
?&gt;</code></pre>

<h5>1.2 API PHP - Lấy danh sách video của một chủ đề</h5>

<p>API này sẽ trả về danh sách video (<code>videoclips_clip</code>) theo <code>parentid</code> của chủ đề.<br  />
&nbsp;</p>

<pre>
<code>&lt;?php
header(&#039;Content-Type: application/json&#039;);
$servername = &quot;localhost&quot;;
$username = &quot;root&quot;;
$password = &quot;&quot;;
$dbname = &quot;your_database_name&quot;;

$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn-&gt;connect_error) {
    die(&quot;Connection failed: &quot; . $conn-&gt;connect_error);
}

$topicid = $_GET&#91;&#039;topicid&#039;&#93;;
$sql = &quot;SELECT * FROM nv4_vi_videoclips_clip WHERE status = 1 AND tid = $topicid&quot;; // nhớ thay nv4_vi_videoclips_clip cho đúng nhé
$result = $conn-&gt;query($sql);

$clips = &#91;&#93;;
if ($result-&gt;num_rows &gt; 0) {
    while($row = $result-&gt;fetch_assoc()) {
        $clips&#91;&#93; = $row;
    }
}

echo json_encode($clips);
$conn-&gt;close();
?&gt;
</code></pre>

<p><br  />
<br  />
&nbsp;</p>

<h4>Bước 2: Thiết lập dự án Android</h4>

<ol>
	<li>
	<p><strong>Tạo một dự án mới</strong> trong Android Studio và chọn ngôn ngữ là <strong>Kotlin</strong>.</p>
	</li>
	<li>
	<p><strong>Thêm quyền truy cập Internet</strong> vào <code>AndroidManifest.xml</code>:</p>
	</li>
</ol>

<pre>
<code class="language-xml">&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;</code></pre>

<h4>Thêm quyền không bắt buộc ssl :&nbsp;android:usesCleartextTraffic=&quot;true&quot; vào thẻ&nbsp;&lt;application&gt; thành như sau</h4>

<pre>
<code>&lt;application
        android:allowBackup=&quot;true&quot;
        android:icon=&quot;@mipmap/ic_launcher&quot;
        android:label=&quot;@string/app_name&quot;
        android:supportsRtl=&quot;true&quot;
        android:usesCleartextTraffic=&quot;true&quot;
        android:theme=&quot;@style/Theme.App1&quot;&gt;</code></pre>

<h4><br  />
Trong file <code>build.gradle</code> (module-level), thêm các thư viện sau để hỗ trợ mạng:<br  />
<br  />
&nbsp;</h4>

<pre>
<code>implementation &#039;com.squareup.retrofit2:retrofit:2.9.0&#039;
implementation &#039;com.squareup.retrofit2:converter-gson:2.9.0&#039;
</code></pre>

<h4><br  />
<br  />
<br  />
Bước 3: Tạo giao diện ứng dụng</h4>

<p>Thiết kế giao diện gồm ba màn hình:</p>

<ul>
	<li><strong>Danh sách chủ đề</strong> (<code>activity_main.xml</code>)</li>
	<li><strong>Danh sách video</strong> (<code>activity_video_list.xml</code>)</li>
	<li><strong>Phát video</strong> (<code>activity_video_player.xml</code>)</li>
</ul>

<p><strong>activity_main.xml</strong> (Danh sách chủ đề)</p>

<pre>
<code class="language-xml">&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:orientation=&quot;vertical&quot;&gt;

    &lt;ListView
        android:id=&quot;@+id/topicListView&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;/&gt;
&lt;/LinearLayout&gt;
</code></pre>
<br  />
<strong>activity_video_list.xml</strong> (Danh sách video)<br  />
&nbsp;
<pre>
<code class="language-xml">&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:orientation=&quot;vertical&quot;&gt;

    &lt;ListView
        android:id=&quot;@+id/videoListView&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;/&gt;
&lt;/LinearLayout&gt;
</code></pre>
<br  />
<strong>activity_video_player.xml</strong> (Phát video)<br  />
&nbsp;
<pre>
<code class="language-xml">&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;&gt;

    &lt;VideoView
        android:id=&quot;@+id/videoView&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_centerInParent=&quot;true&quot; /&gt;
&lt;/RelativeLayout&gt;
</code></pre>

<h4><span style="font-size:16px;"><strong>Bước 4: Code các Activity</strong></span></h4>

<h5><span style="font-size:16px;">MainActivity.kt (Hiển thị danh sách chủ đề)</span></h5>

<pre>
<code>import android.content.Intent
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import com.android.volley.Request
import com.android.volley.toolbox.JsonArrayRequest
import com.android.volley.toolbox.Volley
import org.json.JSONArray
import org.json.JSONException

class MainActivity : AppCompatActivity() {

    private lateinit var topicListView: ListView
    private val topicTitles = mutableListOf&lt;String&gt;()
    private val topicIds = mutableListOf&lt;Int&gt;()
    private val serverUrl = &quot;http://yourwebsite.com/get_topics.php&quot;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        topicListView = findViewById(R.id.topicListView)

        val requestQueue = Volley.newRequestQueue(this)
        val jsonArrayRequest = JsonArrayRequest(
            Request.Method.GET, serverUrl, null,
            { response: JSONArray -&gt;
                for (i in 0 until response.length()) {
                    try {
                        val topic = response.getJSONObject(i)
                        topicTitles.add(topic.getString(&quot;title&quot;))
                        topicIds.add(topic.getInt(&quot;id&quot;))
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                }
                val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, topicTitles)
                topicListView.adapter = adapter
            },
            { error -&gt;
                error.printStackTrace()
            }
        )

        requestQueue.add(jsonArrayRequest)

        topicListView.setOnItemClickListener { _, _, position, _ -&gt;
            val intent = Intent(this, VideoListActivity::class.java)
            intent.putExtra(&quot;tid&quot;, topicIds&#91;position&#93;)
            startActivity(intent)
        }
    }
}
</code></pre>
VideoListActivity.kt (Hiển thị danh sách video)

<pre>
<code>import android.content.Intent
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import com.android.volley.Request
import com.android.volley.toolbox.JsonArrayRequest
import com.android.volley.toolbox.Volley
import org.json.JSONArray
import org.json.JSONException

class VideoListActivity : AppCompatActivity() {

    private lateinit var videoListView: ListView
    private val videoTitles = mutableListOf&lt;String&gt;()
    private val videoPaths = mutableListOf&lt;String&gt;()
    private var serverUrl = &quot;http://yourwebsite.com/get_videos.php?tid=&quot;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video_list)

        videoListView = findViewById(R.id.videoListView)

        val tid = intent.getIntExtra(&quot;tid&quot;, 0)
        serverUrl += tid

        val requestQueue = Volley.newRequestQueue(this)
        val jsonArrayRequest = JsonArrayRequest(
            Request.Method.GET, serverUrl, null,
            { response: JSONArray -&gt;
                for (i in 0 until response.length()) {
                    try {
                        val video = response.getJSONObject(i)
                        videoTitles.add(video.getString(&quot;title&quot;))
                        videoPaths.add(&quot;http://yourwebsite.com/&quot; + video.getString(&quot;internalpath&quot;))
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                }
                val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, videoTitles)
                videoListView.adapter = adapter
            },
            { error -&gt;
                error.printStackTrace()
            }
        )

        requestQueue.add(jsonArrayRequest)

        videoListView.setOnItemClickListener { _, _, position, _ -&gt;
            val intent = Intent(this, VideoPlayerActivity::class.java)
            intent.putExtra(&quot;videoPath&quot;, videoPaths&#91;position&#93;)
            startActivity(intent)
        }
    }
}
</code></pre>
VideoPlayerActivity.kt (Phát video)

<pre>
<code>import android.net.Uri
import android.os.Bundle
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity

class VideoPlayerActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video_player)

        val videoView = findViewById&lt;VideoView&gt;(R.id.videoView)
        val videoPath = intent.getStringExtra(&quot;videoPath&quot;)

        videoView.setVideoURI(Uri.parse(videoPath))
        videoView.setMediaController(MediaController(this))
        videoView.requestFocus()
        videoView.start()
    }
}
</code></pre>
&nbsp;

<h3>Giải thích</h3>

<ul>
	<li><strong>MainActivity</strong>: Gửi request để lấy danh sách chủ đề và hiển thị trên ListView. Khi chọn một chủ đề, mở <code>VideoListActivity</code> để hiển thị các video trong chủ đề đó.</li>
	<li><strong>VideoListActivity</strong>: Gửi request để lấy danh sách video thuộc chủ đề đã chọn và hiển thị trên ListView. Khi chọn một video, mở <code>VideoPlayerActivity</code> để phát video.</li>
	<li><strong>VideoPlayerActivity</strong>: Sử dụng <code>VideoView</code> để phát video từ URL được truyền vào.</li>
</ul>

<h3>Lưu ý</h3>

<ul>
	<li><strong>Thay đổi <code>serverUrl</code></strong> trong mỗi Activity thành URL của API trên máy chủ của bạn.</li>
	<li><strong>Kiểm tra đường dẫn video</strong> trong bảng <code>videoclips_clip</code> để đảm bảo chúng hoạt động.</li>
</ul>

<p>Ứng dụng này cơ bản và phù hợp cho TV hoặc các thiết bị Android khác có màn hình lớn.<br  />
<br  />
Lập trình app tivi với module videos&nbsp;<br  />
Bảng dữ liệu chủ đề video<br  />
<br  />
<img alt="" height="103" src="http://phanmemthienha.com/uploads/news/2024_11/image_1.png" width="1796" /><br  />
<br  />
Bảng dữ liệu các video<br  />
<img alt="" height="139" src="http://phanmemthienha.com/uploads/news/2024_11/image.png" width="1893" /><br  />
<br  />
<br  />
<br  />
<br  />
<br  />
<br  />
<br  />
<br  />
&nbsp;</p>
		</div>
	</div>
	<div id="footer" class="clearfix">
		<div id="url">
			<strong>URL của bản tin này: </strong><a href="http://phanmemthienha.com/news/huong-dan-phan-mem/lap-trinh-android-cho-tivi-220.html" title="Lập trình android cho tivi">http://phanmemthienha.com/news/huong-dan-phan-mem/lap-trinh-android-cho-tivi-220.html</a>

		</div>
		<div class="clear"></div>
		<div class="copyright">
			&copy; PHAN MEM THIEN HA
		</div>
		<div id="contact">
			<a href="mailto:phamhuy842005@gmail.com">phamhuy842005@gmail.com</a>
		</div>
	</div>
</div>
        <div id="timeoutsess" class="chromeframe">
            Bạn đã không sử dụng Site, <a onclick="timeoutsesscancel();" href="http://phanmemthienha.com/#">Bấm vào đây để duy trì trạng thái đăng nhập</a>. Thời gian chờ: <span id="secField"> 60 </span> giây
        </div>
        <div id="openidResult" class="nv-alert" style="display:none"></div>
        <div id="openidBt" data-result="" data-redirect=""></div>
<div id="run_cronjobs" style="visibility:hidden;display:none;"><img alt="" src="/index.php?second=cronjobs&amp;p=l827ada9" width="1" height="1" /></div>
<script src="http://phanmemthienha.com/assets/js/jquery/jquery.min.js"></script>
<script>var nv_base_siteurl="/",nv_lang_data="vi",nv_lang_interface="vi",nv_name_variable="nv",nv_fc_variable="op",nv_lang_variable="language",nv_module_name="news",nv_func_name="savefile",nv_is_user=0, nv_my_ofs=7,nv_my_abbr="ICT",nv_cookie_prefix="nv4c_y8Y7D",nv_check_pass_mstime=1738000,nv_area_admin=0,nv_safemode=0,theme_responsive=1,nv_is_recaptcha=1,nv_recaptcha_sitekey="6LeSarIUAAAAAHRq6xkHwO6J0YYQOdMxgqKTXoL_",nv_recaptcha_type="image",nv_recaptcha_elements=[];</script>
<script src="http://phanmemthienha.com/assets/js/language/vi.js"></script>
<script src="http://phanmemthienha.com/assets/js/global.js"></script>
<script src="http://phanmemthienha.com/themes/default/js/news.js"></script>
<script src="http://phanmemthienha.com/themes/popovleather/js/main.js"></script>
<script src="http://phanmemthienha.com/themes/popovleather/js/bootstrap.min.js"></script>
</body>
</html>