Android集成腾讯X5实现文档浏览功能

Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题。

一、下载腾讯X5内核

1.前往https://x5.tencent.com/下载Android的内核,新版本的腾讯X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把api换成implementation

2.AndroidStudio导入腾讯X5

a.把下载好的jar包导入libs,然后run as,再把jnilibs导入main包下

b. module的build.gradle添加cpu适配

3.Application中腾讯X5初始化,在onCreate()方法调用init方法

QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
   @Override
   public void onCoreInitFinished() {

   }

   @Override
   public void onViewInitFinished(boolean b) {
    Log.e("xxx","hasLoad"+b);
   //此处将内核加载是否成功的状态保存到本地,SharePreference工具类可换为自己的
    SharedPreferenceUtils.saveBoolean(getApplicationContext(),"hasLoad",b);
   }
  });

4.应用内调用,无论是否加载内核,都是把在线的文档下载到本地然后打开,不同的是,未加载内核会借助QQ浏览器或其他App的文件浏览功能类似微信(这个调用,腾讯X5已自动处理,我们无需关心),而加载内核后,使用X5的TbsReaderView来打开文件,接下来就是具体代码。

a.bulid.gradle中集成Retrofit,RxJava和进度管理器ProgressManager

 implementation 'io.reactivex:rxandroid:1.2.1'
 implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
 implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
 implementation 'com.squareup.retrofit2:retrofit:2.3.0'
 implementation 'io.reactivex:rxjava:1.2.6'
 implementation 'me.jessyan:progressmanager:1.5.0'

写网络下载工具

public interface LoadFileApi {
 @GET
 Call<ResponseBody> loadPdfFile(@Url String fileUrl);
}
public class LoadFileModel {
 //使用该方法来下载文件
 public static void loadPdfFile(String url, Callback<ResponseBody> callback) {
  Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://www.baidu.com/")
    .client(ProgressManager.getInstance().with(new OkHttpClient.Builder())
      .build())
    .addConverterFactory(GsonConverterFactory.create())
    .build();
  LoadFileApi mLoadFileApi = retrofit.create(LoadFileApi.class);
  if (!TextUtils.isEmpty(url)) {
   Call<ResponseBody> call = mLoadFileApi.loadPdfFile(url);
   call.enqueue(callback);
  }
 }
}

b.具体调用

首先注册文件进度下载监听

private ProgressDialog commonProgressDialog;//切换为自己的进度控件
 private ProgressInfo mLastDownloadingInfo;
 ProgressManager.getInstance().addResponseListener(url, new ProgressListener() {
            @Override
            public void onProgress(ProgressInfo progressInfo) {
             if (mLastDownloadingInfo == null) {
              mLastDownloadingInfo = progressInfo;
             }
             //因为是以请求开始时的时间作为 Id ,所以值越大,说明该请求越新
             if (progressInfo.getId() < mLastDownloadingInfo.getId()) {
              return;
             } else if (progressInfo.getId() > mLastDownloadingInfo.getId()) {
              mLastDownloadingInfo = progressInfo;
             }
             int progress = mLastDownloadingInfo.getPercent();
             commonProgressDialog.setProgress(progress);
             Log.d("xxx", "--Download-- " + progress + " % " + mLastDownloadingInfo.getSpeed() + " byte/s " + mLastDownloadingInfo.toString());
             if (mLastDownloadingInfo.isFinish()) {
              //说明已经下载完成
              commonProgressDialog.dismiss();
              Log.d("xxx", "--Download-- finish");
             }
            }
            @Override
            public void onError(long id, Exception e) {
             e.printStackTrace();
             new Handler().post(new Runnable() {
              @Override
              public void run() {
                commonProgressDialog.dismiss();
              }
             });
            }
           });
          }

然后打开文件

private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download"; //文件下载的路径,可以自定义
//打开文件
 private void openFile(String filePath,String fileName) {
  boolean hasLoad = SharedPreferenceUtils.getBoolean(mContext, "hasLoad");//是否记载内核
  if (hasLoad){
  //展示文件的Activity
   Intent intentDoc = new Intent(this,FileDisplayActivity.class);
   intentDoc.putExtra("path",filePath);
   intentDoc.putExtra("fileName",fileName);
   startActivity(intentDoc);
  }else {
   if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
    Toast.makeText(this,"当前SD不可用",Toast.LENGTH_LONG).show();
    return;
   }
   try {
    File file = new File(DOWN_DIR, fileName);
    if (file.exists()){
     QbSdk.openFileReader(this, file.getAbsolutePath(), null, new ValueCallback<String>() {
      @Override
      public void onReceiveValue(String s) {
       Log.e("xxx",s);
      }
     });
    } else {
     downLoadFile(filePath,fileName);
    }
   } catch (Exception e) {
    e.printStackTrace();
    ToastUtils.showShortToast(mContext, "已下载过了");
   }
  }
 }
 private void downLoadFile(final String url, final String fileName) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
   @Override
   public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
     if (responseBody != null) {
      is = responseBody.byteStream();
      final File file = new File(DOWN_DIR, fileName);
      fos = new FileOutputStream(file);
      while ((len = is.read(buf)) != -1) {
       fos.write(buf, 0, len);
      }
      fos.flush();
      //未加载内核调用方法
      QbSdk.openFileReader(mContext, file.getAbsolutePath(), null, new ValueCallback<String>() {
       @Override
       public void onReceiveValue(String s) {
        Log.e("xxx",s);
       }
      });
      ToastUtils.showLongToast(MeetingDetailActivity.this, "下载成功,保存在Download文件夹下");
     }
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ProgressManager.getInstance().notifyOnErorr(url,e);
     ToastUtils.showLongToast(MeetingDetailActivity.this, "下载失败");
    } finally {
     try {
      if (is != null)
       is.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     try {
      if (fos != null)
       fos.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
   @Override
   public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(MeetingDetailActivity.this, "下载失败");
    commonProgressDialog.dismiss();
   }
  });
 }

FileDisplayActivity代码,对于一些包名可以切换为自己的包名,还有一些第三方库像进度展示,也可以切换为自己的进度控件

import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.anshi.oatencentschool.R;
import com.anshi.oatencentschool.utils.DialogBuild;
import com.anshi.oatencentschool.utils.StatusBarUtils;
import com.anshi.oatencentschool.utils.ToastUtils;
import com.anshi.oatencentschool.utils.WeakHandler;
import com.anshi.oatencentschool.utils.filetool.LoadFileModel;
import com.anshi.oatencentschool.utils.filetool.SuperFileView2;
import com.kaopiz.kprogresshud.KProgressHUD;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import me.jessyan.progressmanager.ProgressListener;
import me.jessyan.progressmanager.ProgressManager;
import me.jessyan.progressmanager.body.ProgressInfo;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FileDisplayActivity extends AppCompatActivity {
 private String TAG = "FileDisplayActivity";
 //Tencent 提供的TBS阅读浏览功能,不借助第三方软件打开office和pdf文件
 private SuperFileView2 mSuperFileView;
 private String filePath;
 private TextView mTextView;
 private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download";
 private String fileName;
 private KProgressHUD commonProgressDialog;
 private WeakHandler weakHandler = new WeakHandler(new Handler.Callback() {
  @Override
  public boolean handleMessage(Message msg) {
   int progress = msg.arg1;
   if (progress==100){
    commonProgressDialog.setProgress(progress);
    commonProgressDialog.dismiss();
   }else {
    commonProgressDialog.setProgress(progress);
   }
   return true;
  }
 });
 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_file_display);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_FULLSCREEN);
  commonProgressDialog = DialogBuild.getBuild().createCommonProgressDialog(this, "下载中");
  init();
 }
 /**
  * 初始化
  */
 public void init() {
  mTextView = (TextView) findViewById(R.id.file_album_name);
  fileName = getIntent().getStringExtra("fileName");
  int lastIndexOf = fileName.lastIndexOf(".");
  String substring = fileName.substring(0, lastIndexOf);
  mTextView.setText(substring);
  mSuperFileView = (SuperFileView2) findViewById(R.id.mSuperFileView);
  mSuperFileView.setOnGetFilePathListener(new SuperFileView2.OnGetFilePathListener() {
   @Override
   public void onGetFilePath(SuperFileView2 mSuperFileView2) {
    getFilePathAndShowFile(mSuperFileView);
   }
  });
  Intent intent = this.getIntent();
  String path = (String) intent.getSerializableExtra("path");
  if (!TextUtils.isEmpty(path)) {
   Log.d(TAG, "文件path:" + path);
   setFilePath(path);
  }
  mSuperFileView.show();
  ProgressManager.getInstance().addResponseListener(path, new ProgressListener() {
   @Override
   public void onProgress(ProgressInfo progressInfo) {
    int percent = progressInfo.getPercent();
    Message obtain = Message.obtain();
    obtain.arg1 = percent;
    weakHandler.sendMessage(obtain);
   }
   @Override
   public void onError(long id, Exception e) {
   }
  });
 }
 @Override
 protected void onResume() {
  super.onResume();
  StatusBarUtils.setWindowStatusBarColor(this,R.color.color_main);
 }
 /**
  * 显示文件
  * @param mSuperFileView2 控件
  */
 private void getFilePathAndShowFile(SuperFileView2 mSuperFileView2) {
  if (getFilePath().contains("http")&&!new File(DOWN_DIR, fileName).exists()) {//网络地址要先下载
   downLoadFile(getFilePath(),fileName,mSuperFileView2);
  } else {
   try {
    mSuperFileView2.displayFile(new File(DOWN_DIR, fileName));
   }catch (Exception e){
    e.printStackTrace();
   }
  }
 }
 public void setFilePath(String fileUrl) {
  this.filePath = fileUrl;
 }
 private String getFilePath() {
  return filePath;
 }
 /**
  * 回退上一级菜单
  * @param view 控件
  */
 public void onClick(View view) {
  finish();
 }
 private void downLoadFile(final String url, final String fileName,final SuperFileView2 mSuperFileView2) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
   @Override
   public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
      is = responseBody.byteStream();
     final File file = new File(DOWN_DIR, fileName);
     fos = new FileOutputStream(file);
     while ((len = is.read(buf)) != -1) {
      fos.write(buf, 0, len);
     }
     fos.flush();
     mSuperFileView2.displayFile(file);
     ToastUtils.showLongToast(FileDisplayActivity.this, "下载成功,保存在Download文件夹下");
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ToastUtils.showLongToast(FileDisplayActivity.this, "下载失败");
    } finally {
     try {
      if (is != null)
       is.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     try {
      if (fos != null)
       fos.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
   @Override
   public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(FileDisplayActivity.this, "下载失败");
    commonProgressDialog.dismiss();
   }
  });
  }
}

布局Layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_file_display"
 android:layout_width="match_parent"
 android:fitsSystemWindows="true"
 android:layout_height="match_parent">
 <android.support.v7.widget.Toolbar
  android:layout_width="match_parent"
  android:layout_height="46dp"
  android:background="@color/color_main"
  android:id="@+id/file_toolbar"
  >
  <TextView
   android:layout_width="wrap_content"
   android:layout_height="match_parent"
   android:id="@+id/file_album_name"
   android:layout_gravity="center"
   android:gravity="center"
   android:maxLines="2"
   android:ellipsize="end"
   android:textSize="14sp"
   android:textColor="#FFF"
   />
 </android.support.v7.widget.Toolbar>
 <FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_below="@id/file_toolbar"
  >
  <com.anshi.oatencentschool.utils.filetool.SuperFileView2
   android:id="@+id/mSuperFileView"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>
  <RelativeLayout
   android:layout_width="wrap_content"
   android:layout_gravity="center|start"
   android:layout_height="wrap_content">
   <RadioButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:button="@null"
    android:onClick="onClick"
    android:id="@+id/back_icon"
    android:drawableStart="@drawable/svg_left_back_blur"
    android:layout_marginStart="10dp"
    />
  </RelativeLayout>
  <!--<RadioButton-->
   <!--android:layout_width="wrap_content"-->
   <!--android:layout_height="wrap_content"-->
   <!--android:button="@null"-->
   <!--android:visibility="gone"-->
   <!--android:layout_gravity="end|bottom"-->
   <!--android:onClick="saveLocal"-->
   <!--android:layout_marginBottom="10dp"-->
   <!--android:layout_marginEnd="10dp"-->
   <!--android:drawableStart="@drawable/vector_drawable_down_load"-->
   <!--android:layout_marginStart="10dp"-->
   <!--/>-->
 </FrameLayout>
</RelativeLayout>

SuperFileView2代码,这个自定义的类是从https://github.com/ZhongXiaoHong/superFileView导入

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.tencent.smtt.sdk.TbsReaderView;
import java.io.File;
/**
 *
 * Created by 12457 on 2017/8/29.
 */
public class SuperFileView2 extends FrameLayout {
 private static String TAG = "SuperFileView";
 private TbsReaderView mTbsReaderView;
 private Context context;
 public SuperFileView2(Context context) {
  this(context, null, 0);
 }
 public SuperFileView2(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 public SuperFileView2(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  mTbsReaderView = new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
   @Override
   public void onCallBackAction(Integer integer, Object o, Object o1) {
   }
  });
  this.addView(mTbsReaderView, new LinearLayout.LayoutParams(-1, -1));
  this.context = context;
 }
 private OnGetFilePathListener mOnGetFilePathListener;
 public void setOnGetFilePathListener(OnGetFilePathListener mOnGetFilePathListener) {
  this.mOnGetFilePathListener = mOnGetFilePathListener;
 }
 private TbsReaderView getTbsReaderView(Context context) {
  return new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
   @Override
   public void onCallBackAction(Integer integer, Object o, Object o1) {
   }
  });
 }
 public void displayFile(File mFile) {
  if (mFile != null && !TextUtils.isEmpty(mFile.toString())) {
   //增加下面一句解决没有TbsReaderTemp文件夹存在导致加载文件失败
   String bsReaderTemp = Environment.getExternalStorageDirectory()+ File.separator+"TbsReaderTemp";
   File bsReaderTempFile =new File(bsReaderTemp);
   if (!bsReaderTempFile.exists()) {
    Log.d("xxx","准备创建/storage/emulated/0/TbsReaderTemp!!");
    boolean mkdir = bsReaderTempFile.mkdir();
    if(!mkdir){
     Log.d("xxx","创建/storage/emulated/0/TbsReaderTemp失败!!!!!");
    }
   }
   //加载文件
   Bundle localBundle = new Bundle();
   Log.d("xxx",mFile.toString());
   localBundle.putString("filePath", mFile.toString());
   localBundle.putString("tempPath", bsReaderTemp);
   if (mTbsReaderView == null){
    mTbsReaderView = getTbsReaderView(context.getApplicationContext());
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }else {
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }
  } else {
   Log.d("xxx","文件路径无效!");
  }
 }
 /***
  * 获取文件类型
  *
  * @param paramString
  * @return
  */
 private String getFileType(String paramString) {
  String str = "";
  if (TextUtils.isEmpty(paramString)) {
   Log.d(TAG, "paramString---->null");
   return str;
  }
  Log.d(TAG, "paramString:" + paramString);
  int i = paramString.lastIndexOf('.');
  if (i <= -1) {
   Log.d(TAG, "i <= -1");
   return str;
  }
  str = paramString.substring(i + 1);
  Log.d(TAG, "paramString.substring(i + 1)------>" + str);
  return str;
 }
 public void show() {
  if(mOnGetFilePathListener!=null){
   mOnGetFilePathListener.onGetFilePath(this);
  }
 }
 /***
  * 将获取File路径的工作,“外包”出去
  */
 public interface OnGetFilePathListener {
  void onGetFilePath(SuperFileView2 mSuperFileView2);
 }
 public void onStopDisplay() {
  if (mTbsReaderView != null) {
   mTbsReaderView.onStop();
  }
 }
}

加载内核后打开文件

未加载内核打开文件

总结

以上所述是小编给大家介绍的Android集成腾讯X5实现文档浏览功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • Android启动页广告(腾讯广告联盟)解决方法及源码下载

    Android启动页广告(腾讯广告联盟) 启动页几乎成为了每个app的标配,有些商家在启动页中增加了开屏广告以此带来更多的收入.目前启动页的广告都有倒计时的功能,那么我们在倒计时的过程中能做些什么呢? 这篇文章主要包括以下两方面内容 集成腾讯广告联盟的SDK 启动页加载过程中,后台初始化数据 我们在设计启动页时的常规做法是建立一个Activity来加载开屏图片或者广告,作为程序的入口,那么在这个三到五秒时间内如果进行数据下载,当用户点击了跳过按钮或者计时结束了数据还没初始化完成,已经进入了主页面

  • Android实现视频播放--腾讯浏览服务(TBS)功能

    TBS视频播放 TBS视频播放器可以支持市面上几乎所有的视频格式,包括mp4, flv, avi, 3gp, webm, ts, ogv, m3u8, asf, wmv, rm, rmvb, mov, mkv等18种视频格式.同时支持硬件解码,使得内存占用,稳定性相较于系统播放器都更优. 接入TBS 1.导入jar文件和so文件 官网SDK下载地址:https://x5.tencent.com/tbs/sdk.html,示例中有jar文件和so文件,具体导入方式我上一篇文章有详细介绍(Andro

  • 腾讯、百度、华为、搜狗和滴滴Android面试题汇总

    前言:前一段时间和大家交流,据反馈现在Android岗位也没有以前那么多了,当然这不意味着饱和,只是市场更趋于合理一些,Android还有有很多机会的.最近结合一些面试的同学(包含社招和校招),整理了下一些面试题目.实际上,很多面试题网上都能找得到.我整理面试题如下,供大家参考,知道比没知道的好.可以帮大家查漏不缺.以下是(腾讯,百度,华为,搜狗和滴滴 这些厂的面试题) Android基础 View的绘制流程:自定义View如何考虑机型适配:自定义View的事件分发机制:View和ViewGro

  • Android仿微信调用第三方地图应用导航(高德、百度、腾讯)

    实现目标 先来一张微信功能截图看看要做什么 其实就是有一个目的地,点击目的地的时候弹出可选择的应用进行导航. 大脑动一下,要实现这个功能应该大体分成两步: 底部弹出可选的地图菜单进行展示 点击具体菜单某一项的时候调用对应地图的api进行导航就ok啦 底部菜单这里用PopupWindow来做. 实现 1.菜单显示 PopupWindow支持传入view进行弹出展示,所有我们直接写一个菜单布局,高德.百度.腾讯 再加一个取消. map_navagation_sheet.xml <?xml versi

  • Android实战教程第十篇仿腾讯手机助手小火箭发射效果

    之前对系统自带的土司的源码做了简要分析,见博客:点击打开链接 这一篇给一个小案例,自定义土司,模拟腾讯卫士的小火箭发射.如果想要迅速看懂代码,建议先去看一下上篇介绍点击打开链接 首先,定义一个服务,在这个服务里面,完成土司的创建(小火箭布局创建),烟的效果属于动画播放,而且要依托一个activity.(这个activity要定义为透明状态) 定义烟的activity的布局文件 <?xml version="1.0" encoding="utf-8"?>

  • Android集成腾讯X5实现文档浏览功能

    Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题. 一.下载腾讯X5内核 1.前往https://x5.tencent.com/下载Android的内核,新版本的腾讯X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把api换成implementation 2.AndroidStudio导入腾讯X5 a.把下载好的jar包导入

  • Android 使用腾讯X5浏览器上传图片的示例

    目录 1.文件选择 2.实现文件单选 3.举个例子 这几天在客户端接入一个Web页的客服系统,用来接受用户的反馈和建议.Android客户端集成这个客服H5之后,图片死活传递不上去.看了一下iOS同事的集成效果,可以自由上传图片,再把H5的地址用Android原生浏览器打开,也可以正常打开相册上传图片. What??? 见鬼了, 气抖冷!!! 看了一些博客,使用Android的WebView在默认情况下是不能够支持上传文件的(需要重写 onShowFileChooser方法).那就只能撸起袖子自

  • SpringBoot集成Swagger2构建在线API文档的代码详解

    第一部分:代码集成 pom.xml <!--swagger2配置--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>i

  • Springboot集成knife4j实现风格化API文档

    POM引入插件 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <!--在引用时请在maven中央仓库搜索最新版本号 --> <version>2.0.3</version> </dependency> 配置加载 package com.p

  • 教你利用springboot集成swagger并生成接口文档

    效果图 实现步骤 1.maven中引入jar包,不同版本的swagger可能页面效果不一样. <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId&g

  • java集成开发SpringBoot生成接口文档示例实现

    目录 为什么要用Swagger ? Swagger集成 第一步: 引入依赖包 第二步:修改配置文件 第三步,配置API接口 Unable to infer base url For input string: "" Swagger美化 第一步: 引入依赖包 第二步:启用knife4j增强 Swagger参数分组 分组使用说明 1.在bean对象的属性里配置如下注释 2.在接口参数的时候加入组规则校验 小结 大家好,我是飘渺. SpringBoot老鸟系列的文章已经写了两篇,每篇的阅读反

  • spring boot集成smart-doc自动生成接口文档详解

    目录 前言 功能特性 1 项目中创建 /src/main/resources/smart-doc.json配置文件 2 配置内容如下(指定文档的输出路径) 3 pom.xml下添加配置 4 运行插件 5 找到存放路径浏览器打开 6 测试结果 前言 smart-doc 是一款同时支持 java restful api 和 Apache Dubbo rpc 接口文档生成的工具,smart-doc 颠覆了传统类似 swagger 这种大量采用注解侵入来生成文档的实现方法. smart-doc 完全基于

  • Android 通过腾讯TBS实现文件预览功能

    1.集成腾讯TBS 使用腾讯TBS来预览pdf,word,excel,ppt等多种类型的文件,去 腾讯浏览服务官网下载SDK,按照官方文档文档集成SDK. 2.使用TbsReaderView来加载文件 动态创建TbsReaderView,然后添加到布局中. // 回调 TbsReaderView.ReaderCallback readerCallback = new TbsReaderView.ReaderCallback() { @Override public void onCallBack

  • python3+PyQt5实现文档打印功能

    本文通过Python3+PyQt5实现<python Qt Gui 快速编程>这本书13章文档打印功能.本文共通过三种方式: 1.使用HTML和QTextDOcument打印文档 2.使用QTextCusor和QTextDocument打印文档 3.使用QPainter打印文档 使用Qpainter打印文档比QTextDocument需要更操心和复杂的计算,但是QPainter确实能够对输出赋予完全控制. #!/usr/bin/env python3 import math import sy

  • C++ OpenCV实现文档矫正功能

    目录 需求 思路 代码 效果 需求 将一个斜着拍摄的文档矫正成正的,如图所示: 思路 1.读取原始图像,若图像太大可以先进行缩放处理,并获取原始图像的宽和高 2.对图像进行预处理得到边缘,依次进行灰度处理.高斯模糊.边缘检测.膨胀.腐蚀. 3.找到最大的轮廓,并提取角点 进行降噪处理:检测轮廓面积,只保留大于阈值面积的轮廓 计算每个轮廓的周长,使用DP算法计算出轮廓点的个数,规则为周长*0.02 找到图像中面积最大的,且角点为4的轮廓 4.将找到的四个角点排列成一个固定的顺序,排列后的顺序为:左

随机推荐