Android练手小项目之新闻客户端app

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35770741/article/details/78774297

最近写了一个简单的新闻客户端app+后台服务,主要是为了熟悉巩固一下知识点,增加编码熟练度吐舌头

首先来画主界面

实现上图中的页面布局,主要是分成了三部分

最外层使用LinearLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
</LinearLayout>

第一部分RelativeLayout

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dip"
        android:background="#3C3C3C">
        <TextView
            android:id="@+id/main_hand_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="12dp"
            android:text="新闻客户端"
            android:textColor="#e7e7e7"
            android:textSize="18sp" />
        <ImageView
            android:id="@+id/main_hand_refresh"
            android:layout_width="30dip"
            android:layout_height="30dip"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dip"
            android:layout_marginTop="10dip"
            android:onClick="titleBar_image_click"
            android:src="@drawable/main_hand_refresh" />
    </RelativeLayout>

第二部分RelativeLayout

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="1dp"
        android:background="#3C3C3C">
        <HorizontalScrollView
            android:id="@+id/main_category_scroll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/main_category_button"
            android:scrollbars="none">
            <LinearLayout
                android:id="@+id/main_category_linear"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal" />
        </HorizontalScrollView>
        <Button
            android:id="@+id/main_category_button"
            android:layout_width="35dip"
            android:layout_height="35dip"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@drawable/main_category_button" />
    </RelativeLayout>

第三部分是ListView,那为了有下拉刷新的效果,在外层嵌套了SwipeRefreshLayout

    <android.support.v4.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ListView
            android:id="@+id/main_body_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:divider="@drawable/line"
            android:fadeScrollbars="false"
            android:listSelector="@drawable/main_body_list_selector"
            android:scrollbarFadeDuration="0"></ListView>
    </android.support.v4.widget.SwipeRefreshLayout>

接着实现MainActivity代码

package com.mynews.activity;

import android.app.ActionBar;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import com.mynews.R;
import com.mynews.model.News;
import com.mynews.utils.DensityUtil;
import com.mynews.utils.GetPinyin;
import com.mynews.utils.PicassoUtil;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private String CURRENTCATEGORY = "toutiao";  //点击的类别的拼音
    private int COUNT = 1;  //分页的记录值
    private List<News> newsList = new ArrayList<>();  //新闻的集合
    private ListView mainBodyList;   //列表listView
    private View mainBodyListBottom;  //listView底部
    private TextView mainBodyListBottomTV;  //listView底部的TextView
    private ProgressBar mainBodyListBottomPB;  //listView底部的进度条
    private NewsAdapter newsAdapter;  //新闻适配器

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainBodyList = findViewById(R.id.main_body_list);

        //<-----------------------------------设置点击按钮滚动标题栏---------------------------------------
        final HorizontalScrollView category_scrollview = findViewById(R.id.main_category_scroll);
        Button main_category_button = findViewById(R.id.main_category_button);
        main_category_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                category_scrollview.fling(DensityUtil.px2dip(MainActivity.this, 1500)); //滚动方法
            }
        });
        //--------------------------------------------------------------------------------------->

        //-----------------------------------设置点击按钮滚动标题栏--------------------------------------->
        int columnWidth = 400;  //分类间隔距离 px
        String[] categoryArray = getResources().getStringArray(R.array.main_category_item);  //分类信息
        List<Map<String, String>> categorys = new ArrayList<>();
        for (int i = 0; i < categoryArray.length; i++) {
            Map<String, String> map = new HashMap<>();
            map.put("main_category_item", categoryArray[i]);
            categorys.add(map);
        }
        SimpleAdapter categoryAdapter = new SimpleAdapter(this, categorys, R.layout.main_category_item, new String[]{"main_category_item"}, new int[]{R.id.main_category_item});
        //创建网格视图
        GridView gridView = new GridView(this);
        gridView.setNumColumns(GridView.AUTO_FIT);  //列数设置为自动
        gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));  //设置选中颜色为透明色
        gridView.setColumnWidth(DensityUtil.px2dip(this, columnWidth));  //设置列宽,DensityUtil.px2dip()转换px为dip的工具类方法
        gridView.setGravity(Gravity.CENTER);  //设置对齐方式
        int dipColumnWidth = DensityUtil.px2dip(this, columnWidth) * categorys.size();
        ActionBar.LayoutParams params = new ActionBar.LayoutParams(dipColumnWidth, ActionBar.LayoutParams.WRAP_CONTENT);
        gridView.setLayoutParams(params);
        gridView.setAdapter(categoryAdapter);
        LinearLayout categoryLinearlayout = findViewById(R.id.main_category_linear);
        categoryLinearlayout.addView(gridView);
        //<---------------------------------------------------------------------------------------

        //-----------------------------------item的点击事件监听--------------------------------------->
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                TextView categoryTitle;
                //这个循环主要作用清空所有item的背景,并设置初始颜色
                for (int j = 0; j < adapterView.getCount(); j++) {
                    ((TextView) adapterView.getChildAt(j)).setTextColor(getResources().getColor(R.color.color_ADB2AD));
                    adapterView.getChildAt(j).setBackgroundDrawable(null);
                }
                CURRENTCATEGORY = GetPinyin.getPingYin(((TextView) view).getText().toString());  //设置点击后的类别拼音,此处的工具类需要导包 pinyin4j-2.5.0.jar
                COUNT = 1; //分页的记录值
                categoryTitle = (TextView) view;
                categoryTitle.setTextColor(getResources().getColor(R.color.color_FFFFFF));
                categoryTitle.setBackgroundResource(R.drawable.main_category_item_selector);

                newsList = new ArrayList<>();  //清空新闻list
                mainBodyList.removeFooterView(mainBodyListBottom);  //清除底部view
                new NewsTask().execute(getResources().getString(R.string.issue) + "news?type=" + CURRENTCATEGORY);  //异步请求数据 R.string.issue=http://10.0.2.2:8080/news/api/

            }
        });
        //<---------------------------------------------------------------------------------------

        //-----------------------------------listVIew的拖动监听事件监听--------------------------------------->
        mainBodyList.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {  //停止滑动状态
                    if (view.getLastVisiblePosition() == (view.getCount() - 1)) {   //滑动到listView的最后
                        mainBodyListBottomTV.setVisibility(View.GONE);  //隐藏
                        mainBodyListBottomPB.setVisibility(View.VISIBLE);  //显示
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    addData(getResources().getString(R.string.issue) + "news?type=" + CURRENTCATEGORY, COUNT);
                                    handler.sendEmptyMessage(2);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }
                }
            }
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            }
        });
        //<---------------------------------------------------------------------------------------

        new NewsTask().execute(getResources().getString(R.string.issue) + "news?type=" + CURRENTCATEGORY);  //初始化加载
    }

    class NewsTask extends AsyncTask<String, Void, List<News>> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected List<News> doInBackground(String... strings) {
            //使用httpclient需要在app目录下的build.gradle文件中的Android里面加上useLibrary 'org.apache.http.legacy' /*加载 HttpClient*/
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(strings[0]);
            try {
                HttpResponse httpResponse = httpClient.execute(httpGet);
                if (httpResponse.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = httpResponse.getEntity();
                    String json = EntityUtils.toString(entity, "utf-8");
                    JSONArray jsonArray = new JSONObject(json).getJSONArray("pdList");
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject element = jsonArray.getJSONObject(i);
                        News news = new News();
                        news.setNEWSDETAIL_ID(element.getString("NEWSDETAIL_ID"));
                        news.setUNIQUEKEY(element.getString("UNIQUEKEY"));
                        news.setTITLE(element.getString("TITLE"));
                        news.setURL(element.getString("URL"));
                        news.setDATE(element.getString("DATE"));
                        news.setPIC1(element.getString("PIC1"));
                        news.setCATEGORY(element.getString("CATEGORY"));
                        news.setCOMMENT(element.getString("COMMENT"));
                        newsList.add(news);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return newsList;
        }

        @Override
        protected void onPostExecute(List<News> newsList) {
            super.onPostExecute(newsList);
            mainBodyListBottom = getLayoutInflater().inflate(R.layout.main_body_list_bottom, null);
            mainBodyListBottomTV = mainBodyListBottom.findViewById(R.id.main_body_list_bottom_tv);
            mainBodyListBottomPB = mainBodyListBottom.findViewById(R.id.main_body_list_bottom_pb);
            if (newsList.size() == 0) {
                mainBodyListBottomTV.setText("暂无新闻");
            }
            mainBodyList.addFooterView(mainBodyListBottom);
            mainBodyList.setAdapter(newsAdapter = new NewsAdapter(newsList));

            handler.sendEmptyMessage(1);
        }
    }

    class NewsAdapter extends BaseAdapter {
        public List<News> data;
        public NewsAdapter(List<News> data) {
            this.data = data;
        }
        @Override
        public int getCount() {
            return data.size();
        }
        @Override
        public Object getItem(int i) {
            return i;
        }
        @Override
        public long getItemId(int i) {
            return 0;
        }
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            NewsList newsList;
            if (view == null) {
                newsList = new NewsList();
                view = getLayoutInflater().inflate(R.layout.main_body_list_item, viewGroup, false);
                newsList.imageView = view.findViewById(R.id.imageView);
                newsList.textView1 = view.findViewById(R.id.tv_title);
                newsList.textView2 = view.findViewById(R.id.tv_below);
                view.setTag(newsList);
            } else {
                newsList = (NewsList) view.getTag();
            }
            newsList.textView1.setText(data.get(i).getTITLE());
            newsList.textView2.setText(data.get(i).getDATE());
            PicassoUtil.loadImageWithHodler(MainActivity.this, data.get(i).getPIC1(), R.drawable.loading, newsList.imageView);  //使用picasso加载图片资源
            return view;
        }
    }

    class NewsList {
        ImageView imageView;
        TextView textView1;
        TextView textView2;
    }

    /**
     * * 加载分页数据
     *
     * @param count 第几页
     * @param path  地址
     */
    private void addData(String path, int count) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(path + "&count=" + count);
        try {
            HttpResponse httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = httpResponse.getEntity();
                String json = EntityUtils.toString(entity, "utf-8");
                JSONArray jsonArray = new JSONObject(json).getJSONArray("pdList");
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject element = jsonArray.getJSONObject(i);
                    News news = new News();
                    news.setNEWSDETAIL_ID(element.getString("NEWSDETAIL_ID"));
                    news.setUNIQUEKEY(element.getString("UNIQUEKEY"));
                    news.setTITLE(element.getString("TITLE"));
                    news.setURL(element.getString("URL"));
                    news.setDATE(element.getString("DATE"));
                    news.setPIC1(element.getString("PIC1"));
                    news.setCATEGORY(element.getString("CATEGORY"));
                    news.setCOMMENT(element.getString("COMMENT"));
                    newsList.add(news);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {

            }else if(msg.what == 2){  //数据加载完毕
                mainBodyListBottomPB.setVisibility(View.GONE);  //隐藏进度条
                mainBodyListBottomTV.setVisibility(View.VISIBLE);  //显示底部textView
                newsAdapter.notifyDataSetChanged();//刷新listview
                COUNT++;
            }
        }
    };
}


补充:后台服务端代码和接口,点击这里

看看效果,基本实现了主要功能。但是细节做的不太好,找图片资源太耗时了。

接着实现新闻详情界面,顶部的左右箭头绑定了ViewFlipper 的nextView方法  和previousView方法,跟帖数随着发帖数量增加

新闻详情布局主要分为三个部分

最外层使用相对布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/new_detail_rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</RelativeLayout>


第一部分

<RelativeLayout
        android:id="@+id/news_detail_hand_relative"
        android:layout_width="match_parent"
        android:layout_height="50dip"
        android:background="@color/color_D32204">

        <Button
            android:id="@+id/news_detail_hand_relative_btn_left"
            android:layout_width="35dip"
            android:layout_height="35dip"
            android:layout_alignParentLeft="true"
            android:layout_marginTop="6dip"
            android:background="@drawable/zuo" />

        <TextView
            android:id="@+id/news_detail_hand_relative_tv_category"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginVertical="13dip"
            android:layout_toEndOf="@+id/news_detail_hand_relative_btn_left"
            android:textSize="18sp" />

        <Button
            android:id="@+id/news_detail_hand_relative_btn_comment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="20dip"
            android:background="#00000000" />

        <Button
            android:id="@+id/news_detail_hand_relative_btn_right"
            android:layout_width="35dip"
            android:layout_height="35dip"
            android:layout_alignParentRight="true"
            android:layout_marginTop="6dip"
            android:background="@drawable/you" />
    </RelativeLayout>


第二部分,使用ViewFlipper能够加载多个body主体,并能通过方法切换

    <ViewFlipper
        android:id="@+id/news_detail_body_flipper"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/news_detail_hand_relative"
        android:layout_marginBottom="40dip"></ViewFlipper>


第三部分

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dip"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/background"
        android:gravity="center"
        android:orientation="horizontal"
        android:visibility="visible">

        <LinearLayout
            android:id="@+id/news_detail_bottom_ll_01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="3dip"
            android:gravity="center"
            android:orientation="horizontal"
            android:visibility="gone">

            <EditText
                android:id="@+id/news_detail_bottom_ll_01_et_comment"
                android:layout_width="290dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="|" />

            <!--发表-->
            <Button
                android:id="@+id/btn_send"
                android:layout_width="70dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:text="发表" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/news_detail_bottom_ll_02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="3dip"
            android:gravity="center"
            android:orientation="horizontal">

            <ImageButton
                android:id="@+id/news_detail_bottom_ll_02_ib_write"
                android:layout_width="290dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip"
                android:background="#00000000"
                android:src="@drawable/button" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="7dip"
                android:text="|" />

            <!--收藏-->
            <Button
                android:id="@+id/news_detail_bottom_ll_02_btn_collect"
                android:layout_width="60dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:text="收藏" />

        </LinearLayout>

    </LinearLayout>

编写NewsDetailActivity 先把MainActivity中ListView的item点击事件补上

//-----------------------------------listView的item点击事件--------------------------------------->
        mainBodyList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Intent intent = new Intent(MainActivity.this, NewsDetailActivity.class);
                Bundle bundle = new Bundle();
                bundle.putSerializable("list", (Serializable) newsList);//序列化,要注意转化(Serializable)
                intent.putExtra("list", bundle);
                intent.putExtra("i", i);
                startActivity(intent);
            }
        });
        //<---------------------------------------------------------------------------------------

编写NewsDetailActivity

package com.mynews.activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;

import com.mynews.R;
import com.mynews.dao.CollectDao;
import com.mynews.model.Collect;
import com.mynews.model.News;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import java.net.URLEncoder;
import java.util.List;

/**
 * Created by Administrator on 2017/12/28.
 */

public class NewsDetailActivity extends Activity implements View.OnClickListener{

    private String TAG = NewsDetailActivity.class.getSimpleName();
    private Intent intent;  //意图对象
    private int COUNT = 0;  //记录页数
    private List<News> newsList;  //传递过来的list集合
    private TextView tvCategory;  //头部显示新闻类别的文本控件
    private Button btnComment;    //头部的跟帖按钮
    private ViewFlipper viewFlipper;  //view容器
    private LayoutInflater layoutInflater;
    private ProgressBar newsDetailBodyPB;  //主体部分的进度条
    private int mStartX = 0;
    
    private Button newsDetailHandRelativeBtnLeft; //上一篇按钮
    private Button newsDetailHandRelativeBtnRight;  //下一篇按钮
    private ImageButton newsDetailBottomLl02IbWrite;  //图片按钮
    private Button newsDetailBottomLl01BtnSend;  //发送跟帖按钮
    private Button newsDetailBottomLl02BtnCollect;  //收藏按钮

    private long downTime;  //收藏按钮按下的时间
    private long upTime;  //收藏按钮按下的记录时间
    private volatile boolean onBtnTouch = false;  //是否按下按钮

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_detail);

        //-----------------------------------获取MainActivity传递的参数------------------------------------->
        intent = getIntent();  //获取意图对象
        Bundle bundle = intent.getBundleExtra("list");  //获取新闻集合
        newsList = (List<News>) bundle.getSerializable("list");  //新闻集合
        COUNT = intent.getIntExtra("i", 0);  //获取MainActivity点击的item的位置

        //设置头部的新闻类别
        tvCategory = findViewById(R.id.news_detail_hand_relative_tv_category);
        tvCategory.setText(newsList.get(COUNT).getCATEGORY());

        //设置头部的跟帖数
        btnComment = findViewById(R.id.news_detail_hand_relative_btn_comment);
        btnComment.setText(newsList.get(COUNT).getCOMMENT() + "跟帖");

        //设置显示新闻主体
        viewFlipper = findViewById(R.id.news_detail_body_flipper);
        layoutInflater = getLayoutInflater();

        //使用打气筒构造内容主体body
        View view = layoutInflater.inflate(R.layout.news_detail_body, null);

        //设置进度条按钮显示
        newsDetailBodyPB = view.findViewById(R.id.news_detail_body_pb);
        newsDetailBodyPB.setVisibility(View.VISIBLE);

        //viewFlipper.removeAllViews();
        for (int i = 0; i < newsList.size(); i++) {
            View inflate = layoutInflater.inflate(R.layout.news_detail_body, null);
            WebView newsDetailBodyWV = inflate.findViewById(R.id.news_detail_body_wv);
            newsDetailBodyWV.loadUrl(newsList.get(i).getURL());  //设置webView加载URL内容
            viewFlipper.addView(inflate, i);  //把构造的主体内容加入到viewFlipper容器中

            //绑定主体的触摸监听事件
            newsDetailBodyWV.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()) {
                        case MotionEvent.ACTION_DOWN:  //手指按下触发
                            //按下时的横坐标
                            mStartX = (int) motionEvent.getX();
                            break;
                        case MotionEvent.ACTION_UP:  //手指抬起触发
                            //像左滑动
                            if (motionEvent.getX() < mStartX) {
                                nextView();
                            } else if (motionEvent.getX() > mStartX) {  //向右滑动
                                previousView();
                            }
                            break;
                    }
                    return true;
                }
            });
        }
        viewFlipper.setDisplayedChild(COUNT);  //设置第几个view显示
        newsDetailBodyPB.setVisibility(View.GONE);  //进度条隐藏
        //<--------------------------------------------------------------------------------------------------
        
        //---------------------------------------------设置点击事件---------------------------------------------------->
        newsDetailHandRelativeBtnLeft = findViewById(R.id.news_detail_hand_relative_btn_left);//上一页
        newsDetailHandRelativeBtnRight = findViewById(R.id.news_detail_hand_relative_btn_right);//下一页
        newsDetailBottomLl02IbWrite = findViewById(R.id.news_detail_bottom_ll_02_ib_write);//写跟帖
        newsDetailBottomLl01BtnSend = findViewById(R.id.news_detail_bottom_ll_01_btn_send);//发表
        newsDetailHandRelativeBtnLeft.setOnClickListener(this);
        newsDetailHandRelativeBtnRight.setOnClickListener(this);
        newsDetailBottomLl02IbWrite.setOnClickListener(this);
        newsDetailBottomLl01BtnSend.setOnClickListener(this);
        //------------------------------------------------------------------------------------------------->

        //---------------------------------------------设置收藏点击事件---------------------------------------------------->
        newsDetailBottomLl02BtnCollect = findViewById(R.id.news_detail_bottom_ll_02_btn_collect); //收藏 按钮是否被按下
        newsDetailBottomLl02BtnCollect.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    downTime = System.currentTimeMillis();
                    onBtnTouch = true;
                    Thread t = new Thread() {
                        @Override
                        public void run() {
                            while (onBtnTouch) {
                                upTime = System.currentTimeMillis();
                                try {
                                    Thread.sleep(100);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    };
                    t.start();
                } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    onBtnTouch = false;
                    if (upTime - downTime > 500) {
                        handler.sendEmptyMessage(3);  //按下按钮超过0.5秒
                    } else {
                        handler.sendEmptyMessage(2);
                    }
                } else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {  //手指按下移开时触发事件
                    onBtnTouch = false;
                }

                return true;

            }
        });
        //------------------------------------------------------------------------------------------------->

    }

    @Override
    public void onClick(View view) {
        //点击的是上一页
        if (view.getId() == newsDetailHandRelativeBtnLeft.getId()) {
            previousView();
        } else if (view.getId() == newsDetailHandRelativeBtnRight.getId()) {  //点击的是下一页
            nextView();
        } else if (view.getId() == newsDetailBottomLl02IbWrite.getId()) {  //点击的是写跟贴
            LinearLayout ll01 = findViewById(R.id.news_detail_bottom_ll_01);
            ll01.setVisibility(View.VISIBLE);
            LinearLayout ll02 = findViewById(R.id.news_detail_bottom_ll_02);
            ll02.setVisibility(View.GONE);
        } else if (view.getId() == newsDetailBottomLl01BtnSend.getId()) {  //点击的是发表

            final EditText etComment = findViewById(R.id.news_detail_bottom_ll_01_et_comment);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {

                        StringBuffer sb = new StringBuffer();
                        sb.append("content=");
                        sb.append(URLEncoder.encode(etComment.getText().toString().trim(), "UTF-8"));
                        sb.append("&newsdetailId=");
                        sb.append(newsList.get(COUNT).getNEWSDETAIL_ID());
                        String path = getResources().getString(R.string.issue) + "addComment?" + sb.toString();
                        addComment(path);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            Toast.makeText(this, "保存成功!", Toast.LENGTH_SHORT).show();

            LinearLayout ll01 = findViewById(R.id.news_detail_bottom_ll_01);
            ll01.setVisibility(View.GONE);
            LinearLayout ll02 = findViewById(R.id.news_detail_bottom_ll_02);
            ll02.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 添加跟帖
     *
     * @param path 路径
     */
    private void addComment(String path) throws Exception {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(path);
        HttpResponse httpResponse;
        try {
            httpGet.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
            httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = httpResponse.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                // String status = new JSONObject(result).getString("message");
                // String message = new JSONObject(result).getString("status");
                String count = new JSONObject(result).getString("count");

                Message message1 = Message.obtain();
                message1.obj = count;
                message1.what = 1;
                handler.sendMessage(message1);

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

    //点击的是下一页
    private void nextView() {
        COUNT++;
        Log.i(TAG, "nextView: count-->" + COUNT);
        if (COUNT <= newsList.size() - 1) {
            showNext();
        } else {
            COUNT = newsList.size() - 1;
            Toast.makeText(this, "已经是最后一条啦!", Toast.LENGTH_SHORT).show();
        }


    }

    //上一页
    private void previousView() {
        COUNT--;
        Log.i(TAG, "previousView: count-->" + COUNT);
        if (COUNT >= 0) {
            showPrevious();
        } else {
            COUNT = 0;
            Toast.makeText(this, "已经是第一条啦!", Toast.LENGTH_SHORT).show();
        }
    }

    //上一条
    private void showPrevious() {
        btnComment.setText(newsList.get(COUNT).getCOMMENT() + "跟帖");  //设置每条新闻对应的跟帖数量
        //设置动画效果
        viewFlipper.setInAnimation(NewsDetailActivity.this, R.anim.push_right_in);
        viewFlipper.setOutAnimation(NewsDetailActivity.this, R.anim.push_right_out);
        viewFlipper.showPrevious();  //调用viewFlipper的上一条方法
    }

    //下一条
    private void showNext() {
        btnComment.setText(newsList.get(COUNT).getCOMMENT() + "跟帖"); //设置每条新闻对应的跟帖数量
        //设置动画效果
        viewFlipper.setInAnimation(NewsDetailActivity.this, R.anim.push_left_in);
        viewFlipper.setOutAnimation(NewsDetailActivity.this, R.anim.push_left_out);
        viewFlipper.showNext();//调用viewFlipper的下一条方法
    }


    /**
     * 创建一个列表弹窗
     */
    private void createListDialog(final List<Collect> collects) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("收藏列表:");
        builder.setAdapter(new CollectAdapter(collects), new DialogInterface.OnClickListener() {
            /**
             *
             * @param dialogInterface 当前的对话框
             * @param i 当前点击的是列表的第几个 item
             */
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Intent intent = new Intent(NewsDetailActivity.this, CollectNewsDetailActivity.class);
                intent.putExtra("newsdetailId", collects.get(i).getNewsdetailId());
                startActivity(intent);
            }
        });
        builder.setCancelable(true);//允许被某些方式取消,比如按对话框之外的区域或者是返回键
        builder.show();
    }

    class CollectAdapter extends BaseAdapter {
        private List<Collect> collects;
        public CollectAdapter(List<Collect> collects) {
            this.collects = collects;
        }
        @Override
        public int getCount() {
            return collects.size();
        }
        @Override
        public Object getItem(int i) {
            return i;
        }
        @Override
        public long getItemId(int i) {
            return 0;
        }
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            CollectDialog collectDialog;
            if (view == null) {
                collectDialog = new CollectDialog();
                view = getLayoutInflater().inflate(R.layout.news_detail_collect_dialog, viewGroup, false);
                collectDialog.tv1 = view.findViewById(R.id.btn_collect_dialog_title);
                collectDialog.tv2 = view.findViewById(R.id.btn_collect_dialog_date);
                view.setTag(collectDialog);
            } else {
                collectDialog = (CollectDialog) view.getTag();
            }
            collectDialog.tv1.setText(collects.get(i).getTitle());
            collectDialog.tv2.setText(collects.get(i).getDate());
            return view;
        }
    }

    class CollectDialog {
        TextView tv1;
        TextView tv2;
    }

    private Handler handler = new Handler(){
        CollectDao collectDao = new CollectDao(NewsDetailActivity.this);

        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                String count = (String) msg.obj;
                btnComment.setText(count + "跟帖");
            } else if (msg.what == 2) {
                List<Collect> collects = collectDao.queryBuilder1(newsList.get(COUNT).getNEWSDETAIL_ID());
                if (collects.size() <= 0) {
                    Collect collect = new Collect();
                    collect.setNewsdetailId(newsList.get(COUNT).getNEWSDETAIL_ID());
                    collect.setTitle(newsList.get(COUNT).getTITLE());
                    collect.setDate(newsList.get(COUNT).getDATE());
                    collectDao.addCollect(collect);
                    Toast.makeText(NewsDetailActivity.this, "收藏成功,长按可查看收藏哦!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(NewsDetailActivity.this, "已收藏该文章,长按可查看收藏哦!", Toast.LENGTH_SHORT).show();
                }
            } else if (msg.what == 3) {
                createListDialog(collectDao.listAll());
            }
        }
    };
}


NewsDetailActivity 部分在保存收藏文章时使用了ORMLite,需要导入两个jar文件,并且需要编写一个Helper类和一个Dao类。具体看文章最后补上的源码。

接着画下一个布局,界面很简单,直接看代码

布局文件

<?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:background="@color/color_E7E7E7"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/comment_list_hand"
        android:layout_width="match_parent"
        android:layout_height="50dip"
        android:background="@color/color_D32204">

        <TextView
            android:id="@+id/comment_list_hand_TV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="18dip"
            android:layout_marginTop="12dip"
            android:text="跟帖"
            android:textColor="@color/color_E7E7E7"
            android:textSize="18sp" />

        <Button
            android:id="@+id/comment_list_hand_BTN"
            android:layout_width="60dip"
            android:layout_height="45dip"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dip"
            android:layout_marginTop="4dip"
            android:text="原文"/>
    </RelativeLayout>

    <ListView
        android:id="@+id/comment_list_body"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/comment_list_hand"
        android:cacheColorHint="#00000000"
        android:divider="@drawable/line"
        android:layout_marginBottom="40dip">
    </ListView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dip"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/background"
        android:gravity="center"
        android:orientation="horizontal"
        android:visibility="visible">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="3dip"
            android:gravity="center"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/comment_list_bottom_ET"
                android:layout_width="290dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="|" />

            <!--发表-->
            <Button
                android:id="@+id/comment_list_bottom_BTN"
                android:layout_width="70dip"
                android:layout_height="40dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:text="发表" />

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>


编写CommentActivity

package com.mynews.activity;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.mynews.R;
import com.mynews.model.Comment;
import com.mynews.utils.DateUtil;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/12/28.
 */

public class CommentActivity extends Activity {

    private EditText commentListBottomET;  //底部的输入框控件
    private Button commentListBottomBTN;  //底部的发表按钮
    private List<Comment> commentList;  //跟帖集合
    private CommentAdapter commentAdapter;  //跟帖的适配器
    private ListView commentListView;  //跟帖的listView
    private TextView commentListHandTV;
    private Button commentListHandBTN;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.comment_list);

        commentListHandTV = findViewById(R.id.comment_list_hand_TV);
        commentListView = findViewById(R.id.comment_list_body);

        //-----------------------------------原文按钮点击事件----------------------------------------->
        commentListHandBTN = findViewById(R.id.comment_list_hand_BTN);
        commentListHandBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
        //<-------------------------------------------------------------------------------------

        //-----------------------------------发表按钮点击事件----------------------------------------->
        commentListBottomBTN = findViewById(R.id.comment_list_bottom_BTN); //获取发表按钮
        commentListBottomET = findViewById(R.id.comment_list_bottom_ET);   //获取editText按钮
        commentListBottomBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String commentContent = commentListBottomET.getText().toString().trim();
                            StringBuffer sb = new StringBuffer();
                            sb.append("content=");
                            sb.append(URLEncoder.encode(commentContent, "UTF-8"));
                            sb.append("&newsdetailId=");
                            sb.append(getIntent().getStringExtra("newsdetailId"));
                            String path = getResources().getString(R.string.issue) + "addComment?" + sb.toString();
                            addComment(path);

                            Comment comment = new Comment();
                            comment.setDATE(DateUtil.getTime());
                            comment.setCONTENT(commentContent);
                            commentList.add(comment);
                            handler.sendEmptyMessage(2);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });

        new CommentTask().execute(getResources().getString(R.string.issue) + "commentList?newsdetailId=" + getIntent().getStringExtra("newsdetailId"));
    }

    class CommentAdapter extends BaseAdapter {

        private List<Comment> commentList;

        public CommentAdapter(List<Comment> commentList) {
            this.commentList = commentList;
        }

        @Override
        public int getCount() {
            return commentList.size();
        }

        @Override
        public Object getItem(int i) {
            return i;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            Comment1 comment1;
            if (view == null) {
                comment1 = new Comment1();
                view = getLayoutInflater().inflate(R.layout.comment_list_item, viewGroup, false);
                comment1.tv1 = view.findViewById(R.id.comment_list_item_tv1);
                comment1.tv2 = view.findViewById(R.id.comment_list_item_tv2);
                comment1.tv3 = view.findViewById(R.id.comment_list_item_tv3);
                view.setTag(comment1);
            } else {
                comment1 = (Comment1) view.getTag();
            }
            comment1.tv1.setText(commentList.get(i).getDATE());
            comment1.tv2.setText(commentList.get(i).getCOMMENTID());
            comment1.tv3.setText(commentList.get(i).getCONTENT());
            return view;
        }
    }

    class Comment1 {
        TextView tv1;
        TextView tv2;
        TextView tv3;
    }

    class CommentTask extends AsyncTask<String, Void, List<Comment>> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected List<Comment> doInBackground(String... strings) {
            commentList = new ArrayList<>();
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(strings[0]);
            try {
                HttpResponse httpResponse = httpClient.execute(httpGet);
                if (httpResponse.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = httpResponse.getEntity();
                    String json = EntityUtils.toString(entity, "utf-8");
                    JSONArray jsonArray = new JSONObject(json).getJSONArray("pdList");
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject element = jsonArray.getJSONObject(i);
                        Comment comment = new Comment();
                        comment.setCOMMENTID(element.getString("COMMENT_ID"));
                        comment.setDATE(element.getString("DATE"));
                        comment.setCONTENT(element.getString("CONTENT"));
                        commentList.add(comment);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return commentList;
        }

        @Override
        protected void onPostExecute(List<Comment> commentList) {
            super.onPostExecute(commentList);
            commentListView.setAdapter(commentAdapter = new CommentAdapter(commentList));
        }
    }

    /**
     * 添加跟帖
     *
     * @param path 路径
     */
    private void addComment(String path) throws Exception {
        //Log.i(TAG, "addComment: path------>>" + path);
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(path);
        HttpResponse httpResponse;
        try {
            httpGet.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
            //httpGet.addHeader("charset", HTTP.UTF_8);
            httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = httpResponse.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                String status = new JSONObject(result).getString("message");
                String message = new JSONObject(result).getString("status");
                String count = new JSONObject(result).getString("count");
                Message message1 = Message.obtain();
                message1.obj = count;
                message1.what = 1;
                handler.sendMessage(message1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                String count = (String) msg.obj;
                commentListHandTV.setText("跟帖 " + count + "条");
                Toast.makeText(CommentActivity.this, "发帖成功!", Toast.LENGTH_LONG).show();
            } else if (msg.what == 2) {
                commentAdapter.notifyDataSetChanged();//刷新listview
                commentListBottomET.setText("");  //清空文本
                commentListBottomET.clearFocus();  //清除焦点
                //软键盘隐藏
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    };

}

到此主要的功能以及基本实现,现在再来给主界面添加上版本更新的代码,让程序每次启动检查是否有新版本,并提示用户是否更新

package com.mynews.dao;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.mynews.BuildConfig;
import com.mynews.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

public class VersionDao {

    private Context context;
    private Map<String, String> map;  //服务器端最新app信息
    private volatile boolean cancelUpdate;  //下载状态
    private ProgressBar pbNewsDeatil;
    private Dialog downloadDialog;
    private String TAG = VersionDao.class.getSimpleName();

    public VersionDao(Context context, Map<String, String> map) {
        this.context = context;
        this.map = map;
    }

    public void checkUpdate() {
        Log.i(TAG, "checkUpdate: 版本更新");
        if (isUpdate()) {
            showNoticeDialog();
        }
    }

    private boolean isUpdate() {
        //获取当前软件版本号
        String versionName = getVersionName();
        //Log.i(TAG, "isUpdate: versionName=" + versionName);
        //Log.i(TAG, "isUpdate: NUMBER=" + map.get("NUMBER").toString());
        if (!versionName.equals(map.get("NUMBER").toString())) {  //版本号字符串不相等时更新
            return true;
        }
        return false;
    }

    /**
     * 当前应用版本号
     *
     * @return 版本号
     */
    private String getVersionName() {
        String versionName = null;
        try {
            //通过上下文对象获取版本号
            versionName = context.getPackageManager().getPackageInfo("com.gm.news", 0).versionName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return versionName;
    }

    private void showNoticeDialog() {
        //构造对话框
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("版本更新提示");
        builder.setMessage("检测到新版本," + map.get("CONTENT").toString());
        //更新
        builder.setPositiveButton("更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();  //隐藏更新对话框
                showDownloadDialog();  //显示下载进度对话框
            }
        });

        //稍后更新
        builder.setNegativeButton("稍后更新", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        });
        Dialog noticeDialog = builder.create();
        noticeDialog.show();
    }

    private void showDownloadDialog() {
        Log.i(TAG, "showDownloadDialog: 弹出更新对话框");
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("更新进度:");
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        View view = layoutInflater.inflate(R.layout.main_softupload_progress, null);
        pbNewsDeatil = view.findViewById(R.id.pb_newsDetail);
        TextView tv_version_content = view.findViewById(R.id.tv_version_content);
        tv_version_content.setText(map.get("CONTENT").toString());  //版本更新的内容
        builder.setView(view);
        //取消
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
                //设置取消状态
                cancelUpdate = false;
            }
        });

        downloadDialog = builder.create();
        downloadDialog.show();
        cancelUpdate = true;  //开始下载
        //下载文件
        download();

    }

    //下载文件
    private void download() {
        Log.i(TAG, "download: 下载文件中");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {

                    URL url = new URL(map.get("PATH").toString());
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    int code = conn.getResponseCode();
                    if (code == HttpURLConnection.HTTP_OK) {
                        File file = new File(context.getFilesDir().getPath() + "/mynews.apk");
                        FileOutputStream fos = new FileOutputStream(file);
                        float length = conn.getContentLength();
                        InputStream in = conn.getInputStream();
                        float total = 0;
                        int len = -1;
                        byte[] buffer = new byte[100];
                        int progress;
                        while ((len = in.read(buffer)) != -1) {
                            if (cancelUpdate) {
                                fos.write(buffer, 0, len);
                                total += len;
                                progress = (int) ((total / length) * 100);
                                pbNewsDeatil.setProgress(progress);
                            }
                        }
                        in.close();
                        fos.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 进度达到最大值后,窗口消失
                downloadDialog.cancel();
                install();
            }
        }).start();
    }

    private void install() {
        File file = new File(context.getFilesDir().getPath() + "/mynews.apk");
        Intent intent = new Intent(Intent.ACTION_VIEW);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);
    }
}


在MainActivity的onCreate方法中调用

 new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String path = getResources().getString(R.string.issue) + "findVersion";
                    findVersion(path);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
/**
     * 查询版本信息
     *
     * @param path
     */
    private void findVersion(String path) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(path);
        HttpResponse httpResponse;
        try {
            httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = httpResponse.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                JSONObject jsonObject = new JSONObject(result).getJSONObject("pd");
                map = new HashMap<>();
                map.put("VERSION_ID", jsonObject.getString("VERSION_ID"));
                map.put("NUMBER", jsonObject.getString("NUMBER"));
                map.put("CONTENT", jsonObject.getString("CONTENT"));
                map.put("DATE", jsonObject.getString("DATE"));
                map.put("STATUS", jsonObject.getString("STATUS"));
                map.put("PATH", jsonObject.getString("PATH"));
                handler.sendEmptyMessage(4);  //数据请求加载完毕发送消息让handler处理
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

handler中进行处理

if (msg.what == 4) {  //版本更新的逻辑
                VersionDao versionDao = new VersionDao(MainActivity.this, map);
                versionDao.checkUpdate();  //更新操作
            }

清单文件中配置

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mynews.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>


res文件夹下新建xml文件夹,新建文件file_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path
        name="external_files"
        path="" />
</paths>

运行程序查看效果

可能有一部分功能代码逻辑处理的并不是很好或是有BUG,还请各位多多包涵。

源码下载地址

猜你喜欢

转载自blog.csdn.net/qq_35770741/article/details/78774297