如何让制作一个网络书城

项目目录设置

拓展知识

maven私服配置

maven仓库分为远端服务器和私服
maven结构图
那为什么用私服呢?
在这里插入图片描述

  • 节省自己的外网带宽
    建立私服可以减少组织自己的开支,大量的对于外部远程仓库的重复请求会消耗很大的带宽,利用私服代理外部仓库后,对外的重复构件下载得以消除,即降低外网带宽的压力。

  • 加速Maven的构建
    不停的请求外部仓库无疑是比较耗时的, 但Maven的一些内部机制(如快照检测)要求Maven在执行构建的时候不停地检查远程仓库的数据。
    因此当配置了很多远程仓库时,构建的速度会被大大降低。使用私服可以很好地解决这个问题。

  • 部署第三方构件
    当某个构件无法从外部远程仓库下载怎么办?
    这样的例子很多,如组织内部的生成的私有的构件肯定无法从外部仓库获取,Oracle的JDBC驱动由于版权原因不能发布到外网的中心仓库。
    建立私服之后便可以将这些构件部署到本地私服中,供内部的Maven项目使用。

  • 提高稳定行,增强控制
    Maven构建搞定依赖于远程仓库,因此,当Internet不稳定的时候,Maven构建也会变的不稳定,甚至无法构建。
    使用私服后即使暂时没有Internet连接Maven也可以正常运行,因为私服中缓存了大量的构件。
    此外一些私服软件(如:Nexus)还提供了很多额外的功能,如权限管理,RELEASE/SNAPSHOT区分等,管理员可以对仓库进行一些更高级的控制。

  • 降低中央仓库的负荷
    数百万的请求,存储数T的数据,需要相相当大的财力。使用私服可以避免很多对中央仓库的重复请求。

下一步就是安装nexus了

nexus 安装等教程这里有一篇很好的博文可以参考一下

apache Http网页服务器

接下来就是了解一下apache http服务器
Apache HTTP Server(简称Apache),是Apache软件基金会的一个开放源代码的网页服务器,可以在大多数电脑操作系统中运行,由于其具有的跨平台性和安全性,被广泛使用,是最流行的Web服务器端软件之一。来自百度词条
知道是个什么就要下载配置安装
配置过程可以参考apache安装等教程

做完这两步我们来看一下怎么配置一下整个项目目录

bmob 后端云设置(可选作为用户设置)

bmob配置方式

制作程序

相关配置

我们看一下图片上的一些介绍,然后我们进行代码的编写
在这里插入图片描述
首先是等待页
等待也就是一个点击程序时候可以有一个广告页面,这个页面可以跳过或者不跳过
splash页面
这里放入关键代码

public class SplashActivity extends BaseUIActivity{
    public static final int CODE = 1001;
    public static final int TOTAL_TIME = 3000;
    public static final int INTERVAL_TIME = 1000;

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        mTextView = (TextView) findViewById(R.id.time_text_view);

        final Handler handler = new MyHandler(this);

        Message message = Message.obtain();
        message.what = CODE;
        message.arg1 = TOTAL_TIME;
        handler.sendMessage(message);

        mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                BookListActivity.start(SplashActivity.this);
                SplashActivity.this.finish();
                handler.removeMessages(CODE);
            }
        });


    }

    public static class MyHandler extends Handler {
        public final WeakReference<SplashActivity> mWeakReference;

        public MyHandler(SplashActivity activity) {
            mWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            SplashActivity activity = mWeakReference.get();
            if (msg.what == CODE) {
                if (activity != null) {

                    // 设置textview,更新UI
                    int time = msg.arg1;
                    activity.mTextView.setText(time / INTERVAL_TIME + "秒,点击跳过");

                    // 发送倒计时

                    Message message = Message.obtain();
                    message.what = CODE;
                    message.arg1 = time - INTERVAL_TIME;

                    if (time > 0) {
                        sendMessageDelayed(message, INTERVAL_TIME);
                    } else {
                        BookListActivity.start(activity);
                        activity.finish();
                    }

                }
            }
        }

    }


}

在这一段里面可以看到,我们的程序界面的设置,但是我们发现,没有BaseUIActivity这个类,我们来看下他是干什么的
在这里插入图片描述

public class BaseUIActivity extends BaseActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        SystemUI.fixSystemUI(this);
    }
}

名字可以看出,我写了一个重置UI的选项,那这个是怎么实现的

public class SystemUI {
    public static void fixSystemUI(Activity mActivity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //获取最顶层的View
            mActivity.getWindow().getDecorView()
                    .setSystemUiVisibility(
                            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            mActivity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
    }
}

这里要检查一下程序的版本,所以单独写一个类来实现,那接下来要做的就是进入之后的显示类 BookListActivity
书单
这些数据全部来自网络端,那网络端要怎么实现,之前提到apache HTTP 看一下列表
文件关系
在这里插入图片描述
上代码

/**
 * FileName BookListActivity
 *
 * @author ziqin
 * @version 1.0
 * @date 2020/12/17 18:03
 * Descriptopn: 书籍列表类
 */
public class BookListActivity extends BaseActivity {
    private static final String TAG = "BookListActivity";
    private ListView mListView;
    private List<BookListResult.Book> mBooks = new ArrayList<>();
    private AsyncHttpClient mClient;

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

        init();
    }

    private void init() {
        mListView = (ListView) findViewById(R.id.book_list_view);
        String url ="http://10.0.2.2:8888/lib.json";
        mClient = new AsyncHttpClient();
        mClient.get(url, new AsyncHttpResponseHandler() {
            @Override
            public void onStart() {
                super.onStart();

            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                final String result = new String(responseBody);

                Gson gson = new Gson();
                BookListResult bookListResult = gson.fromJson(result, BookListResult.class);

                mBooks = bookListResult.getData();

                mListView.setAdapter(new BookListAdapter());


            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

            }

            @Override
            public void onFinish() {
                super.onFinish();
            }
        });
    }

    /**
     * 权限申请
     */
    private void requsetPermiss() {
        //危险权限
        request(new OnPermissionsResult() {
            @Override
            public void OnSuccess() {

            }
            @Override
            public void OnFail(List<String> noPermissions) {
                Log.i("noPermissions:", noPermissions.toString());
            }
        });
    }
    public static void start(Context context) {
        Intent intent = new Intent(context, BookListActivity.class);
        context.startActivity(intent);
    }


    private class BookListAdapter extends BaseAdapter {

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

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

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

        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            final BookListResult.Book book = mBooks.get(position);

            ViewHolder viewHolder = new ViewHolder();
            if (view == null) {
                view = getLayoutInflater().inflate(R.layout.item_book_list_view, null);
                viewHolder.mNameTextView = (TextView) view.findViewById(R.id.name_text_view);
                viewHolder.mButton = (Button) view.findViewById(R.id.book_btn);
                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            viewHolder.mNameTextView.setText(book.getBookname());
            final String path = Environment.getExternalStorageDirectory() + "/yuedukongjian/" + book.getBookname() + ".txt";
            Log.i(TAG,ExistSDCard()+"");
            Log.i(TAG,path);

            File file = new File(path);
            // try {
            //     file.createNewFile();
            // } catch (IOException e) {
            //     e.printStackTrace();
            // }
            // try {
            //     FileWriter fileWriter = new FileWriter(file);
            //     fileWriter.write("sssss");
            // } catch (IOException e) {
            //     e.printStackTrace();
            // }



            viewHolder.mButton.setText(file.exists() ? "点击打开" : "点击下载");

            final ViewHolder finalViewHolder = viewHolder;
            viewHolder.mButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (file.exists()) {
                        BookActivity.start(BookListActivity.this, path);
                    } else {
                        mClient.addHeader("Accept-Encoding", "identity");
                        mClient.get(book.getBookfile(), new FileAsyncHttpResponseHandler(file) {
                            @Override
                            public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) {
                                finalViewHolder.mButton.setText("下载失败");
                            }

                            @Override
                            public void onSuccess(int statusCode, Header[] headers, File file) {
                                finalViewHolder.mButton.setText("点击打开");
                            }

                            @Override
                            public void onProgress(long bytesWritten, long totalSize) {
                                super.onProgress(bytesWritten, totalSize);
                                finalViewHolder.mButton.setText(String.valueOf(bytesWritten * 100 / totalSize) + "%");
                            }
                        });

                    }

                }
            });

            return view;
        }

        class ViewHolder {
            public TextView mNameTextView;
            public Button mButton;
        }
    }
    private boolean ExistSDCard() {
        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            return true;
        } else
            return false;
    }

    //第一次按下时间
    private long firstClick;

    @Override
    public void onBackPressed() {
        AppExit();
        //super.onBackPressed();
    }

    /**
     * 再按一次退出
     */
    public void AppExit() {
        if (System.currentTimeMillis() - this.firstClick > 2000L) {
            this.firstClick = System.currentTimeMillis();
            Toast.makeText(this, "再按一次退出", Toast.LENGTH_LONG).show();
            return;
        }
        finish();
    }

}

这里用到AsyncHttp,小文件完全够了,并且用的是listview,也可以考虑替换,这里已经够用了就不考虑
里面涉及到一个端口在init()里面,可以看一下这里对应上面的HTTP设置 10.0.2.2是android studio对主机地址的取值
String url ="http://10.0.2.2:8888/lib.json";
接下来获取到json我们可以先打印出来,对应的用插件转换为对应的类

并且对下载放了一个对应的加载数据 看最后一本书,点击之后显示下载的进度
在这里插入图片描述


public class BookListResult {

    @SerializedName("status")
    private int mStatus;
    @SerializedName("msg")
    private String mMessage;

    @SerializedName("data")
    private List<Book> mData;

    public int getStatus() {
        return mStatus;
    }

    public void setStatus(int status) {
        mStatus = status;
    }

    public String getMessage() {
        return mMessage;
    }

    public void setMessage(String message) {
        mMessage = message;
    }

    public List<Book> getData() {
        return mData;
    }

    public void setData(List<Book> data) {
        mData = data;
    }

    public static class Book {
        @SerializedName("bookname")
        private String mBookname;
        @SerializedName("bookfile")
        private String mBookfile;

        public String getBookname() {
            return mBookname;
        }

        public void setBookname(String bookname) {
            mBookname = bookname;
        }

        public String getBookfile() {
            return mBookfile;
        }

        public void setBookfile(String bookfile) {
            mBookfile = bookfile;
        }
    }
}

json文件如下

{
  "status": 1,
  "data": [
    {
      "bookname": "大主宰",
      "bookfile": "http://10.0.2.2:8888/txt/大主宰.txt"
    },
    {
      "bookname": "鬼吹灯",
      "bookfile": "http://10.0.2.2:8888/txt/鬼吹灯.txt"
    },
    {
      "bookname": "盘龙",
      "bookfile": "http://10.0.2.2:8888/txt/大主宰.txt"
    },
    {
      "bookname": "庆余年",
      "bookfile": "http://10.0.2.2:8888/txt/庆余年.txt"
    },
    {
      "bookname": "圣墟",
      "bookfile": "http://10.0.2.2:8888/txt/圣墟.txt"
    },
    {
      "bookname": "心理罪",
      "bookfile": "http://10.0.2.2:8888/txt/心理罪.txt"
    },
    {
      "bookname": "重生九零小俏媳",
      "bookfile": "http://10.0.2.2:8888/txt/重生九零小俏媳.txt"
    }
  ],
  "msg": "成功"
}

贝塞尔曲线类这里准备了直接导入的类,不赘述

那我们就要提一下,集成的动态权限
上代码

/**
 * FileName BaseActivity
 *
 * @author ziqin
 * @version 1.0
 * @date 2020/12/23 19:20
 * Descriptopn:
 */
public class BaseActivity extends AppCompatActivity {
    //申请运行时权限的Code
    private static final int PERMISSION_REQUEST_CODE = 1000;

    //申明所需权限
    private String[] mStrPermission = {
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
    };

    //保存没有同意的权限
    private List<String> mPerList = new ArrayList<>();
    //保存没有同意的失败权限
    private List<String> mPerNoList = new ArrayList<>();

    private OnPermissionsResult permissionsResult;

    /**
     * 一个方法请求权限
     *
     * @param permissionsResult
     */
    protected void request(OnPermissionsResult permissionsResult) {
        if (!checkPermissionsAll()) {
            requestPermissionAll(permissionsResult);
        }
    }

    /**
     * 判断单个权限
     *
     * @param permissions
     * @return
     */
    protected boolean checkPermissions(String permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int check = checkSelfPermission(permissions);
            return check == PackageManager.PERMISSION_GRANTED;
        }
        return false;
    }

    /**
     * 判断是否需要申请权限
     *
     * @return
     */
    protected boolean checkPermissionsAll() {
        mPerList.clear();
        for (int i = 0; i < mStrPermission.length; i++) {
            boolean check = checkPermissions(mStrPermission[i]);
            //如果不同意则请求
            if (!check) {
                mPerList.add(mStrPermission[i]);
            }
        }
        return mPerList.size() > 0 ? false : true;
    }

    /**
     * 请求权限
     *
     * @param mPermissions
     */
    protected void requestPermission(String[] mPermissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(mPermissions, PERMISSION_REQUEST_CODE);
        }
    }

    /**
     * 申请所有权限
     *
     * @param permissionsResult
     */
    protected void requestPermissionAll(OnPermissionsResult permissionsResult) {
        this.permissionsResult = permissionsResult;
        requestPermission((String[]) mPerList.toArray(new String[mPerList.size()]));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        mPerNoList.clear();
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0) {
                for (int i = 0; i < grantResults.length; i++) {
                    if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                        //你有失败的权限
                        mPerNoList.add(permissions[i]);
                    }
                }
                if (permissionsResult != null) {
                    if (mPerNoList.size() == 0) {
                        permissionsResult.OnSuccess();
                    } else {
                        permissionsResult.OnFail(mPerNoList);
                    }
                }
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    protected interface OnPermissionsResult {
        void OnSuccess();

        void OnFail(List<String> noPermissions);
    }
}

有了这些之后,我们就要来绘制一下点进书籍的时候显示的页面,不过有的方法正在淘汰,要注意一下

public class BookActivity extends AppCompatActivity {


    public static final String FILE_PATH = "file_path";
    public static final String BOOKMARK = "bookmark";
    private BookPageView mBookPageView;
    private TextView mProgressTextView;
    private View mSettingView;
    private RecyclerView mRecyclerView;
    private static final String TAG = "BookActivity";
    private int mCurrentLength;
    private BookPageBezierHelper mHelper;
    private Bitmap mCurrentPageBitmap;
    private Bitmap mNextPageBitmap;
    private String mFilePath;
    private int mWidth;
    private int mHeight;
    private int mLastLength;
    private TextToSpeech mTTS;
    private SeekBar mSeekBar;
    private int mTotalLength;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // fullscreen
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }

        setContentView(R.layout.activity_book);

        if (getIntent() != null) {
            mFilePath = getIntent().getStringExtra(FILE_PATH);
            if(!TextUtils.isEmpty(mFilePath)){
                mTotalLength = (int) new File(mFilePath).length();
            }
        } else {
            // todo  can not find the book path
        }
        // init view
        mBookPageView = (BookPageView) findViewById(R.id.book_page_view);
        mProgressTextView = (TextView) findViewById(R.id.progress_text_view);
        mSettingView = findViewById(R.id.setting_view);
        mRecyclerView = (RecyclerView) findViewById(R.id.settingRecyclerView);
        mSeekBar = (SeekBar) findViewById(R.id.seekBar);

        // get Size
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mWidth = displayMetrics.widthPixels;
        mHeight = displayMetrics.heightPixels;
        openBookByProgress(R.drawable.book_bg, 0);
        //set progress

        mHelper.setOnProgressChangedListener(new BookPageBezierHelper.OnProgressChangedListener() {
            @Override
            public void setProgress(int currentLength, int totalLength) {
                mCurrentLength = currentLength;
                float progress = mCurrentLength * 100 / totalLength;
                mProgressTextView.setText(String.format("%s%%", progress));
            }
        });

        // set user setting view listener.

        mBookPageView.setOnUserNeedSettingListener(new BookPageView.OnUserNeedSettingListener() {
            @Override
            public void onUserNeedSetting() {
                mSettingView.setVisibility(mSettingView.getVisibility() == View.VISIBLE
                        ? View.GONE : View.VISIBLE);
            }
        });

        // set recyclerView data.

        List<String> settingList = new ArrayList<>();
        settingList.add("添加书签");
        settingList.add("读取书签");
        settingList.add("设置背景");
        settingList.add("语音朗读");
        settingList.add("跳转进度");

        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(new HorizontalAdapter(this, settingList));

        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                openBookByProgress(R.drawable.book_bg, seekBar.getProgress()* mTotalLength /100);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                openBookByProgress(R.drawable.book_bg, seekBar.getProgress()* mTotalLength /100);
            }
        });
    }
    private void openBookByProgress(int backgroundResourceID, int progress) {
        // set book helper
        mHelper = new BookPageBezierHelper(mWidth, mHeight, progress);
        mBookPageView.setBookPageBezierHelper(mHelper);

        // current page , next page
        mCurrentPageBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        mNextPageBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        mBookPageView.setBitmaps(mCurrentPageBitmap, mNextPageBitmap);

        // set background
        mHelper.setBackground(this, backgroundResourceID);
        // open book
        if (!TextUtils.isEmpty(mFilePath)) {
            try {
                mHelper.openBook(mFilePath);
                mHelper.draw(new Canvas(mCurrentPageBitmap));
                mBookPageView.invalidate();
            } catch (IOException e) {
                e.printStackTrace();
                // todo  can not find the book path
            }
        } else {
            // todo  can not find the book path
        }
    }

    public static void start(Context context, String filePath) {
        Intent intent = new Intent(context, BookActivity.class);
        intent.putExtra(FILE_PATH, filePath);
        context.startActivity(intent);

    }

    private class HorizontalAdapter extends RecyclerView.Adapter {

        private Context mContext;
        private List<String> mData = new ArrayList<>();

        public HorizontalAdapter(Context context, List<String> list) {
            mContext = context;
            mData = list;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            TextView itemView = new TextView(mContext);
            return new ViewHolder(itemView);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
            TextView textView = (TextView) holder.itemView;
            textView.setWidth(350);
            textView.setHeight(180);
            textView.setTextSize(16);
            textView.setTextColor(Color.WHITE);
            textView.setGravity(Gravity.CENTER);
            textView.setText(mData.get(position));
            final SharedPreferences sharedPreferences =
                    mContext.getSharedPreferences("yuedu_book_preference", MODE_PRIVATE);

            final SharedPreferences.Editor editor = sharedPreferences.edit();

            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    switch (position) {
                        case 0:
                            // add bookmark
                            // get progress
                            // save progress to preference.
                            editor.putInt(BOOKMARK, mCurrentLength);
                            editor.apply();
                            break;
                        case 1:
                            // get bookmark from preference.
                            // reload book to the progress.
                            mLastLength = sharedPreferences.getInt(BOOKMARK, 0);
                            openBookByProgress(R.drawable.book_bg, mLastLength);
                            break;
                        case 2:
                            openBookByProgress(R.drawable.book_bg2, mLastLength);
                            break;
                        case 3:
                            if (mTTS == null) {
                                mTTS = new TextToSpeech(mContext, new TextToSpeech.OnInitListener() {
                                    @Override
                                    public void onInit(int status) {
                                        if (status == TextToSpeech.SUCCESS) {
                                            int result = mTTS.setLanguage(Locale.CHINA);
                                            if (result == TextToSpeech.LANG_MISSING_DATA
                                                    || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                                                Log.e(TAG, "onInit: language is not available.");
                                                Uri uri = Uri.parse("http://acj2.pc6.com/pc6_soure/2017-6/com.iflytek.vflynote_208.apk");
                                                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                                                startActivity(intent);
                                            } else {
                                                Log.i(TAG, "onInit: init success.");
                                                // mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null);
                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                                    mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null, "悦读");
                                                } else {
                                                    mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null);
                                                }
                                            }
                                        } else {
                                            Log.e(TAG, "onInit: error");
                                        }
                                    }
                                });
                            } else {
                                if (mTTS.isSpeaking()) {
                                    mTTS.stop();
                                } else {
                                    // mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null);
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                        mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null, "悦读");
                                    } else {
                                        mTTS.speak(mHelper.getCurrentPageContent(), TextToSpeech.QUEUE_FLUSH, null);
                                    }
                                }
                            }
                            break;
                        case 4:
                            mSeekBar.setVisibility(View.VISIBLE);
                            break;
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder {

            private TextView mTextView;

            public ViewHolder(TextView itemView) {
                super(itemView);
                mTextView = itemView;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mTTS != null){
            mTTS.shutdown();
        }
    }
}

另外的功能可根据需要看代码怎么实现,也可以引用一些接口实现语音功能

 List<String> settingList = new ArrayList<>();
        settingList.add("添加书签");
        settingList.add("读取书签");
        settingList.add("设置背景");
        settingList.add("语音朗读");
        settingList.add("跳转进度");

成果

书籍显示
书籍显示,这里要注意一下看一下服务器端的解析,否则会乱码

添加背景和翻页效果

在这里插入图片描述
结束

网上书店的设计与实现 作 者: 指导老师: (湖南信息学院电子信息学院2012级软件设计,长沙 410151) 摘要: 网上书店系统是建立在Internet网上进行商务活动的虚拟网络空间和保障商务顺利运营的管理环境;是协调、整合信息流、物质流、资金流有序、关联、高效流动的重要场所。网上商家、合作商家、企业和网络客户可充分利用在线书城提供的网络基础设施、支付平台、安全平台、管理平台等共享资源有效地、低成本地开展自己的商务活动。 网上书店系统是基于B/S模式的小型电子商务系统,能够满足中小型书店的网上售书需要。 系统采用Visual Studio作为开发平台,以MS SQL Server 2000 作为 后台数据库来完成对系统的设计和开发。主要开发流程为:对基于WEB的网上购物系统进行可行性分析,并对资源分配、进度安排等做出合理的计划后,对该系统进行了需求分析、概要设计和详细设计,最后对每个模块进行了编码,并进一步对完成好的系统进行了测试和运行。 说明书首先对电子商务的基础知识和构建网上书店的关键业务进行了阐述。其次用面向对象的方法分析并设计了一个网上书店系统,其中涉及了网上书店系统开发的模式、后台关系型数据库的设计、工具及环境的说明。本网站开发过程中将依照软件生命周期法则,在需求分析阶段进行了功能需求分析、非功能性需求,其中包括系统业务流程分析。同时对数据库中的关键技术和分析方法也做了详细的阐述。基本囊括了一个电子商务网站的开发制作流程和应该予以重视的要点问题。 关键词:电子商务;网上购物;数据库;动态建模
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值