원본출처: 티스토리 바로가기
오늘은 내 앱의 화면에 올라온 내용중에 webView 에 들어 있는 것을 이미지 파일로 만들고 pdf 파일에 담아서 공유하는 기능을 구현해 보고자 한다.
먼저할 것은 인터넷 접속을 위한 권한 부여
<uses-permission android:name="android.permission.INTERNET"/>
굳이 사용자에게 허가를 받지 않아도 된다. 그 다음에 layout 을 구성해 보았다.
보는 것 처럼 화면에는 버튼 한개와 webView 만 한개 만들어 두었다.
layout의 코드는 다음과 같이.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/pdfShare" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="40dp" android:layout_marginTop="16dp" android:text="Button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <WebView android:id="@+id/webView" android:layout_width="0dp" android:layout_height="645dp" android:layout_marginTop="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/pdfShare" /> </androidx.constraintlayout.widget.ConstraintLayout>
그 다음은 이미지를 임시로 저장하고 그걸 pdf 로 전환하는 방법을 구현할 예정이기 때문에 임시저장소를 선택할 수 있도록 file_provider 의 값을 등록해 준다. res/xml 폴더에 file_provider.xml 로 아래 내용을 저장해 주었다.
cache 을 사용하는 것은 파일 저장을 하기 위해서 사용자에게 권한을 허가 받지 않아도 되기 떄문이다.
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="cache" path="."/> </paths>
다음은 activity을 구현해 보아야겠다.
먼저 webView 에 나의 블로그를 load할 수 있도록 하고, load가 다 되었다면 그 때 이미지 파일에 임시 저장을 한 다음,
버튼을 클릭하면 그 이미지 파일을 열어서 공유하는 intent 을 호출 하도록 구현할 예정이다.
import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.app.ActivityCompat; import androidx.core.app.ShareCompat; import androidx.core.content.FileProvider; import android.Manifest; import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.pdf.PdfDocument; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import com.billcoreatech.pdftest.databinding.ActivityMainBinding; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; Bitmap bitmap, scalebmp ; int pageWidth = 1200 ; ActivityMainBinding bind ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); bind = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(bind.getRoot()); bind.webView.loadUrl("https://billcorea.tistory.com"); bind.webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); new Background().execute(); } }); bind.pdfShare.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (createPDF ()) { File pdfFile = new File(getCacheDir(), "/pizza.pdf"); Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName()+".fileProvider", pdfFile); Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("application/pdf"); shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(shareIntent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } startActivity(Intent.createChooser(shareIntent, "PDF 공유")); }; } }); } private boolean createPDF() { File file = new File(getCacheDir(), "/aaaa.png"); if (!file.isFile()) { Toast.makeText(getApplicationContext(), "파일 생성이 되지 않았습니다.", Toast.LENGTH_SHORT).show(); return false ; } bitmap = BitmapFactory.decodeFile(getCacheDir().toString() + "/aaaa.png"); PdfDocument pdfDocument = new PdfDocument(); Paint paint = new Paint(); PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create(); PdfDocument.Page page = pdfDocument.startPage(pageInfo); Canvas canvas = page.getCanvas(); canvas.drawBitmap(bitmap, 0, 0, paint); pdfDocument.finishPage(page); File file1 = new File(getCacheDir(), "/pizza.pdf"); try { pdfDocument.writeTo(new FileOutputStream(file1)); } catch (IOException e) { return false ; } pdfDocument.close(); return true ; } class Background extends AsyncTask<Void, Void, Bitmap> { @Override protected Bitmap doInBackground(Void... params) { try { Thread.sleep(2000); Bitmap bitmap = Bitmap.createBitmap(bind.webView.getWidth(), bind.webView.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); bind.webView.draw(canvas); return bitmap; } catch (InterruptedException e){} catch (Exception e){} return null; } @SuppressLint("WrongThread") @Override protected void onPostExecute(Bitmap bm) { try { OutputStream fOut = null; File file = new File(getCacheDir(), "/aaaa.png"); fOut = new FileOutputStream(file); bm.compress(Bitmap.CompressFormat.PNG, 50, fOut); fOut.flush(); fOut.close(); bm.recycle(); Log.e(TAG, "fileName=" + getCacheDir() + "/aaaa.png"); Toast.makeText(getApplicationContext(), "공유할 파일이 생성되었습니다.", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "" + e.toString()); } } } }
webView 에 load는 시간이 소요 되기 떄문에 Background 로 load 된 이미지를 png 로 변환하도록 구현이 되었고,
버튼을 클릭하면 그 때 png 파일이 있는 지 체크 해서 없으면 알림을 보여주고, 있으면 해당 이미지 파일을 pdf 로 전환해서 하고, pdf 가 생성되었다면, intent 을 호출해서 공유하도록 구현하는 방식이다.
다만, API 32 기준으로 AVD에서 테스트를 해 보면서 오류 로그가 보이기는 했으나, 실행은 되었다. provider 에게 uri read 권한을 주어야 할 것 같은데, 아직 구글링을 했을 때 정확한 해소 방안은 찾을 수 없었다.
어떻게 하지 ?
알게될 날이 올까 ?
오류 해소를 위해서 다음 링크 까지는 해 보았으나... 아직 ... ㅠㅠ;;
댓글
댓글 쓰기