热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android新闻App的本地服务器搭建教程

本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。

如今的APP许多都是要联网获取数据的,比如新闻客户端,如果想要尝试下这个流程的话,那么就需要有服务器和数据库了。在服务器上搭建各种环境是十分繁琐的,所以我们可以选择搭建一个本地服务器,然后在手机端获取其数据库内的数据。

这里选用XAMPP
XAMPP 是一个整合型的Apache套件,包含Apache、MySQL、PHP、PERL,可以一键式搭建起开发环境,推荐初学者使用。官方网址——https://www.apachefriends.org/zh_cn/index.html

软件开启后的界面是:

这里写图片描述

这里点击start开启Apache和MySQL就好,点击admin可以进入控制界面。

首先进入phpmyadmin界面,新建一个数据库 news,再建立一张表 new,为其建立六个属性,分别是:

id 主键
title 文章标题
description 摘要
date 文章发表时间
newUrl 文章链接
imageUrl 图片链接

创建new表的SQL语句如下

CREATE TABLE `new` (
`id` int(11) NOT NULL,
`title` text NOT NULL,
`description` text NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`newUrl` text NOT NULL,
`imageUrl` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

new表插入数据

这里写图片描述

手机端的工作就是来读取数据并显示出来,不过手机端也无法直接访问数据库内容。所以在数据库端需要利用PHP将数据库内容返回为JSON格式的数据,然后手机端再去解析JSON数组

首先是进行数据库连接
mysql_connect.php


//数据库的用户名为root,密码为空
$con = mysql_connect("localhost", "root", "");
//设置字符集为utf8
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET CHARACTER_SET_RESULT=utf8");

if (!$con){
die(mysql_error());
}
//访问数据库news
mysql_select_db("news", $con);
?>

接下来是将读取到的数据库内容返回为JSON数组
getNewsJSON.php


/*
* 获得JSON数据
*/

require 'mysql_connect.php';
$n = 0;
$result = mysql_query("select * from new");
while ($row = mysql_fetch_array($result)){
$arr[$n++] = array("title" => $row['title'],
"description" => $row['description'],
"date" => $row['date'],
"newUrl" => $row['newUrl'],
"imageUrl" => $row['imageUrl']
);
}
//数组转换为JSON字符串
echo json_encode($arr);
?>

将两个php文件放到XAMPP安装目录的htdocs文件夹下,直接存放或者再新建个文件夹存放也可以,例如我的存放路径就是:C:\xampp\htdocs\news

然后打开浏览器,输入http://localhost/news/getNewsJSON.php
如果是呈现如下格式的数据,那就说明数据库数据读取成功了。没有直接呈现中文字符是因为编码问题,无需理会。

这里写图片描述

服务器端开发完毕了,接下来就要进行移动端的设计了。

新建个工程。要做的是一个新闻客户端,新闻列表就采用RecyclerView来呈现,将默认布局改为:


<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.zy.news.MainActivity">


<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent">
android.support.v7.widget.RecyclerView>

RelativeLayout>

列表的子项布局:
new_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#f7f9fa"
android:orientation="horizontal"
android:padding="6dp">


<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/new_image"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_gravity="center" />


<LinearLayout
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="6dp">


<TextView
android:id="@+id/new_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@android:color/black"
android:textSize="20sp"
android:textStyle="bold" />


<TextView
android:id="@+id/new_introduction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="4"
android:textColor="@android:color/black"
android:textSize="16sp" />


<TextView
android:id="@+id/new_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="6dp"
android:textColor="@android:color/black"
android:textSize="13sp" />

LinearLayout>
LinearLayout>

SimpleDraweeView是Fresco推出的一款图片加载控件,导入SimpleDraweeView的方法是在build.gradle文件下加入语句compile 'com.facebook.fresco:fresco:0.10.0',然后点击同步即可

这里写图片描述

前边在建表时时设立了六个属性,除去主键id外,一篇新闻还有五个属性。为新闻建立一个实体NewIntroduction.java,省略相应的get和set属性。

public class NewIntroduction {
//文章标题
private String title;
//文章摘要
private String description;
//文章发表时间
private String date;
//文章链接
private String newUrl;
//图片链接
private String imageUrl;
}

新建一个NewsItemListAdapter.java文件,继承自RecyclerView.Adapter,作为RecyclerView的适配器

/**
* Created by ZY on 2016/6/10.
*/

public class NewsItemListAdapter extends RecyclerView.Adapter {

private List introductionList;

private LayoutInflater inflater;

public NewsItemListAdapter(Context context, List introductionList) {
this.introductiOnList= introductionList;
this.inflater = LayoutInflater.from(context);
}

@Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.new_item, parent, false);
return new NewsHolder(view);
}

@Override
public void onBindViewHolder(NewsHolder holder, int position) {
holder.new_image.setImageURI(Uri.parse(introductionList.get(position).getImageUrl()));
holder.new_title.setText(introductionList.get(position).getTitle());
holder.new_introduction.setText(introductionList.get(position).getDescription());
holder.new_date.setText(introductionList.get(position).getDate());
}

@Override
public int getItemCount() {
if (introductiOnList== null || introductionList.size() == 0) {
return 0;
}
return introductionList.size();
}
}

NewsHolder也是一个自定义类,继承自RecyclerView.ViewHolder

/**
* Created by ZY on 2016/6/10.
*/

public class NewsHolder extends RecyclerView.ViewHolder {

public SimpleDraweeView new_image;

public TextView new_title;

public TextView new_introduction;

public TextView new_date;

public NewsHolder(View itemView) {
super(itemView);
new_image = (SimpleDraweeView) itemView.findViewById(R.id.new_image);
new_title = (TextView) itemView.findViewById(R.id.new_title);
new_introduction = (TextView) itemView.findViewById(R.id.new_introduction);
new_date = (TextView) itemView.findViewById(R.id.new_date);
}

}

修改MainActivity

public class MainActivity extends AppCompatActivity {

private List newIntroductionList;

private NewsItemListAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fresco.initialize(this);
setContentView(R.layout.activity_main);

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycleView);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

newIntroductiOnList= new ArrayList<>();
adapter = new NewsItemListAdapter(MainActivity.this, newIntroductionList);
recyclerView.setAdapter(adapter);
}
}

此时newIntroductionList 内还没有填充数据,程序打开后还是一片空白,所以接下来就要来获取本地服务器内的数据

新建一个Util类
getNewsJSon(String strUrl)方法用来访问getNewsJSON.php页面,获取页面数据

public static String getNewsJSon(String strUrl) throws IOException {
URL url;
URLConnection urlConnection;
HttpURLConnection httpURLConnection;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = null;
try {
url = new URL(strUrl);
urlCOnnection= url.openConnection();
httpURLCOnnection= (HttpURLConnection) urlConnection;
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
reader = new BufferedReader(inputStreamReader);
resultBuffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
resultBuffer.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
}
if (resultBuffer == null) {
return null;
}
return resultBuffer.toString();
}

getNewIntroductionList(String strUrl)方法用来解析JSON数组

public static List<NewIntroduction> getNewIntroductionList(String strUrl) throws IOException {
String html = getNewsJSon(strUrl);
if (html == null) {
return null;
}
List<NewIntroduction> newIntroductionList = new ArrayList<>();
try {
JSONArray jsonArray = new JSONArray(html);

for (int i = 0; i < jsonArray.length(); i++) {
NewIntroduction newIntroduction = new NewIntroduction();
JSONObject jsonObject = jsonArray.optJSONObject(i);
String title = jsonObject.getString("title");
String description = jsonObject.getString("description");
String date = jsonObject.getString("date");
String newUrl = jsonObject.getString("newUrl");
String imageUrl = jsonObject.getString("imageUrl");

newIntroduction.setTitle(title);
newIntroduction.setDescription(description);
newIntroduction.setDate(date);
newIntroduction.setNewUrl(newUrl);
newIntroduction.setImageUrl(imageUrl);

newIntroductionList.add(newIntroduction);
}

} catch (JSONException e) {
e.printStackTrace();
}

return newIntroductionList;
}

然后在MainActivity文件中建立一个内部类MyAsyncTask继承自

AsyncTask<String, Void, List<NewIntroduction>>

用来进行联网操作。将读取到的JSON数组解析为NewIntroduction对象,传入适配器中

 class MyAsyncTask extends AsyncTask<String, Void, List<NewIntroduction>> {

@Override
protected List doInBackground(String... params) {
List newIntroductiOnList= null;
try {
newIntroductiOnList= Util.getNewIntroductionList(params[0]);
} catch (IOException e) {
e.printStackTrace();
}
return newIntroductionList;
}

@Override
protected void onPostExecute(List introductionList) {
if (introductiOnList== null || introductionList.size() == 0) {
return;
}
MainActivity.this.newIntroductionList.addAll(introductionList);
MainActivity.this.adapter.notifyDataSetChanged();
}
}

然后在onCreate(Bundle savedInstanceState)方法的最后一行new一个MyAsyncTask对象即可。模拟器访问本地服务器的IP地址为10.0.2.2,所以完整的访问地址应为http://10.0.2.2/news/getNewsJSON.php

new MyAsyncTask().execute("http://10.0.2.2/news/getNewsJSON.php");

最后还要加上联网访问权限

<uses-permission android:name="android.permission.INTERNET" />

程序运行结果如下:

这里写图片描述

代码下载地址:一个简单的联网新闻客户端的开发思路


推荐阅读
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 深入解析JVM垃圾收集器
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • 本文详细介绍了HTML中标签的使用方法和作用。通过具体示例,解释了如何利用标签为网页中的缩写和简称提供完整解释,并探讨了其在提高可读性和搜索引擎优化方面的优势。 ... [详细]
author-avatar
华福-日语人才_601
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有