Android实战开发小米主题下载工具

本站已经对小米主题真实地址进行解析了,https://lovestu.com/3.html,那么现在使用Android Studio开发一款解析APP

准备工作

okhttp是一款非常优秀的互联网访问类库,可以减少很多的代码编写,所以这儿使用okhttp方式进行数据访问,首先创建一个项目,添加OKhttp依赖

  1. compile 'com.squareup.okhttp:okhttp:2.4.0'
  2. compile 'com.squareup.okio:okio:1.7.0'

然后点击同步,进行下载依赖库

还有最重要的联网权限和写读写文件权限

  1. <uses-permission android:name="android.permission.INTERNET"/>
  2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

有这三个权限才能正常的读写文件和联网

开始代码编写

创建一个mithemedown类,解析代码都在这儿编写了,创建一个获取网页源码的函数,本函数的功能是通过传入的主题唯一ID获取网页源码,调用的是OKhttp的同步访问方法,在外部使用的时候需要用到线程

  1. import com.squareup.okhttp.OkHttpClient;
  2. import com.squareup.okhttp.Request;
  3. import com.squareup.okhttp.Response;
  4. public class mithemedown {
  5. public static String getdownurl(String value) {
  6. final String url = "http://thm.market.xiaomi.com/thm/download/v2/" + value;
  7. String Strjson = "";
  8. try {
  9. OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
  10. Request request = new Request.Builder()
  11. .url(url)//请求接口。如果需要传参拼接到接口后面。
  12. .build();//创建Request 对象
  13. Response response = null;
  14. response = client.newCall(request).execute();//得到Response 对象
  15. if (response.isSuccessful()) {
  16. Strjson = response.body().string();
  17. }
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. return Strjson;
  22. }
  23. }

接着我们开始制作界面,界面很简单,两个编辑框,一个是正常的EditText,另一个是多行文本框,所以要给这个EditText添加android:inputType=”textMultiLine”属性,然后设置行数android:minLines=”8″ ,两个按钮,还需要一个进度条ProgressBar。点击解析按钮后会进行解析,把解析到的地址给显示到第二个编辑框,然后点击立即下载后调用下载系统下载功能进行下载主题

Android实战开发小米主题下载工具

完整xml代码如下,基于ConstraintLayout布局创建

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context="com.ghboke.mithemedown.MainActivity">
  8. <ProgressBar
  9. android:id="@+id/progressBar"
  10. style="?android:attr/progressBarStyle"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:visibility="invisible"
  14. app:layout_constraintBottom_toBottomOf="parent"
  15. app:layout_constraintLeft_toLeftOf="parent"
  16. app:layout_constraintRight_toRightOf="parent"
  17. app:layout_constraintTop_toTopOf="parent" />
  18. <LinearLayout
  19. android:id="@+id/linearLayout"
  20. android:layout_width="0dp"
  21. android:layout_height="0dp"
  22. android:layout_marginBottom="8dp"
  23. android:layout_marginEnd="8dp"
  24. android:layout_marginStart="8dp"
  25. android:layout_marginTop="8dp"
  26. android:orientation="vertical"
  27. app:layout_constraintBottom_toBottomOf="parent"
  28. app:layout_constraintEnd_toEndOf="parent"
  29. app:layout_constraintStart_toStartOf="parent"
  30. app:layout_constraintTop_toTopOf="parent">
  31. <EditText
  32. android:id="@+id/editText_url"
  33. android:layout_width="match_parent"
  34. android:layout_height="wrap_content"
  35. android:ems="10"
  36. android:hint="输入主题地址"
  37. android:inputType="textPersonName" />
  38. <Button
  39. android:id="@+id/button_jx"
  40. android:layout_width="match_parent"
  41. android:layout_height="wrap_content"
  42. android:text="解析" />
  43. <EditText
  44. android:id="@+id/editText_downurl"
  45. android:layout_width="match_parent"
  46. android:layout_height="wrap_content"
  47. android:ems="10"
  48. android:inputType="textMultiLine"
  49. android:minLines="8" />
  50. <Button
  51. android:id="@+id/Button_down"
  52. android:layout_width="match_parent"
  53. android:layout_height="wrap_content"
  54. android:text="立即下载" />
  55. </LinearLayout>
  56. </android.support.constraint.ConstraintLayout>

制作好界面以后,去MainActivity中绑定组件

  1. private ProgressBar mProgressBar;
  2. private EditText mEditTextUrl;
  3. private Button mButtonJx;
  4. private EditText mEditTextDownurl;
  5. private Button mButtonDown;
  6. private String downurl;
  7. private boolean candown=false;
  8. private String filename;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. initView();
  14. }
  15. private void initView() {
  16. mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
  17. mEditTextUrl = (EditText) findViewById(R.id.editText_url);
  18. mButtonJx = (Button) findViewById(R.id.button_jx);
  19. mButtonJx.setOnClickListener(this);
  20. mEditTextDownurl = (EditText) findViewById(R.id.editText_downurl);
  21. mButtonDown = (Button) findViewById(R.id.Button_down);
  22. mButtonDown.setOnClickListener(this);
  23. }

绑定好以后,给按钮设置点击事件,重写布局的onClick函数

  1. @Override
  2. public void onClick(View v) {
  3. switch (v.getId()) {
  4. default:
  5. break;
  6. case R.id.button_jx:
  7. jx();
  8. break;
  9. case R.id.Button_down:
  10. down();
  11. break;
  12. }
  13. }

点击按钮就会执行相应的函数,首先编写点击解析按钮的事件 jx(),点击解析按钮后,首先要判断用户是否输入了内容,如果没有输入内容会返回。再接着,获取到输入的网址以后,从31位开始截取网址,因为我们只需要后面的唯一标识。

比如小米主题的地址是http://zhuti.xiaomi.com/detail/e9f4d15d-1a4c-408a-a80c-73c046ff46d8,其中网址的e9f4d15d-1a4c-408a-a80c-73c046ff46d8这一段数据才是我们需要的,所以我们就从这段网址第31位开始截取到全部,即可获取到唯一标识。

再一个是调用最开始的获取网页源码的函数的时候,由于我们给类设置了statc,所以可以直接调用,启动一个线程,在启动线程的时候,给ProgressBar设置为可视状态,因为他默认是圆圈的进度条,所以刚好符合我们需要。解析成功后,需要到主线程里面更新UI,runOnUiThread函数会自动跳到主线程里面,所以在线程中调用这个方法即可更新UI,无需Handler。

下面是完整的代码

  1. public void jx() {
  2. downurl = mEditTextUrl.getText().toString();
  3. if (downurl.length() == 0) {
  4. Toast.makeText(getApplicationContext(), "请输入网址", Toast.LENGTH_LONG).show();
  5. return;
  6. }
  7. downurl = downurl.substring(31);
  8. mProgressBar.setVisibility(View.VISIBLE);
  9. new Thread(new Runnable() {
  10. @Override
  11. public void run() {
  12. downurl = mithemedown.getdownurl(downurl);
  13. try {
  14. JSONObject json = new JSONObject(downurl);
  15. JSONObject downobj = json.getJSONObject("apiData");
  16. downurl = downobj.getString("downloadUrl");
  17. } catch (JSONException e) {
  18. e.printStackTrace();
  19. }
  20. runOnUiThread(new Runnable() {
  21. @Override
  22. public void run() {
  23. if (downurl.length()==0){
  24. Toast.makeText(getApplicationContext(), "解析失败", Toast.LENGTH_LONG).show();
  25. candown=false;
  26. return;
  27. }else {
  28. Toast.makeText(getApplicationContext(), "解析成功", Toast.LENGTH_LONG).show();
  29. }
  30. candown=true;
  31. mEditTextDownurl.setText(downurl);
  32. mProgressBar.setVisibility(View.INVISIBLE
  33. );
  34. }
  35. });
  36. }
  37. }).start();
  38. }

接着是下载按钮的功能.down()函数。点击函数,我们先判断用户是否解析成功,再调用下载功能。其中程序集变量candown用来记录是否解析成功,在jx()函数中,如果解析成功了,允许调用下载

  1. public void down() {
  2. if (candown==false){
  3. Toast.makeText(getApplicationContext(), "请解析成功后再使用", Toast.LENGTH_LONG).show();
  4. return;
  5. }
  6. filename=downurl.substring(91);
  7. try {
  8. filename=decode(filename, "utf-8");
  9. } catch (UnsupportedEncodingException e) {
  10. e.printStackTrace();
  11. }
  12. File file=new File(Environment.getExternalStorageDirectory() + "/MIThemeDown/"+filename);
  13. if (file.exists()){
  14. Toast.makeText(getApplicationContext(), "文件已经下载过啦", Toast.LENGTH_LONG).show();
  15. return;
  16. }
  17. DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downurl));
  18. request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
  19. request.setTitle(filename);
  20. request.setAllowedOverRoaming(false);
  21. request.setDescription("小米主题下载");
  22. request.setVisibleInDownloadsUi(true);
  23. request.setDestinationInExternalPublicDir("/MIThemeDown/",filename);
  24. DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
  25. long downloadId = downloadManager.enqueue(request);
  26. Toast.makeText(getApplicationContext(), "已经开始下载", Toast.LENGTH_LONG).show();
  27. }

好了,这个软件大致的功能就写完了,是不是很简单

最终效果

Android实战开发小米主题下载工具

完善代码

程序到最后,还有很多需要完善的地方,比如说判断用户是否乱输入了地址,如果长度没有31位长度,那么截取就可以出问题。

还有部分系统需要手动声明读写文件的权限才能调用系统下载功能DownloadManager,并且上面的代码并没有创建文件夹,还需要自动创建一个主题文件保存的目录。

下载的权限请求函数请查看:https://lovestu.com/5.html

下载地址:http://download.****.net/download/applek_case/10254039