Webview PDF

  • Antworten:26
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 19:37:01 via Website

Hallo ihr Lieben. Ich habe eine frage, unzwar habe ich meine App soweit fertig und auch getestet, aber die PDF lässt sich nicht öffnen auf meiner Website. Vorweg es ist keine feste PDF url da es eine Kleinanzeigen seite ist. Also müsste das so sein das es nur die PDF zulässt bzw die url Öffnet.

Mit freundlichen Grüßen
Roberto.

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 22:48:33 via App

Hallo Roberto,

Android kann in einer WebView keine PDFs anzeigen.
Da musst du wohl HTML PDF Viewer einsetzen.
Gibts von Google (weiß aber nicht mehr wie es heißt) oder PDF.JS von Mozilla. Kannst du dir entweder auf deinem Server installieren oder über die Mozilla URL einbinen.

Was genau willst du damit machen?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 22:52:22 via Website

Pascal, also meine Website ist e8ne kleinanzeigen seite wo man auch eine pdf zum ausdrucken hat.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 22:59:40 via App

Dann geht das nicht.
Die PDF kannst du nur zum Download anbieten und dann hoffen dass der Nutzer eine App zum PDF ansehen oder ausdrucken hat.
Inzwischen sollten das die meisten Geräte durch Google Apps aber können

— geändert am 15.04.2020, 23:00:33

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 23:02:56 via Website

Pascal, ja es reicht wenn man auf dem button klickt von der website und es dann runderladen tut. Aber wie kann ich das zulassen ?

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 23:12:53 via Website

Okay aber es gibt da keine feste PDF url weil es da immer eine neu PDF gibt bei jeder kleinanzeige also kann ich das quasie so machen das nur das downloaden freigegeben wird.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 23:18:19 via App

Kannst du nicht.
Du kannst die Downlads auf *.pdf einschränken vlt noch auf ebay-kleinanzeigen server aber sonst nicht ohne sie PDFs auf eigenem Server zu haben

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 23:21:41 via Website

Also die PDF sind auf mein Server da mache ich quasie *.pdf und nicht https wenn ich das richtig verstanden habe.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 23:22:26 via App

hast du mal ein Beispiel?
Verlinkst du die PDF auf der Kleinanzeigen seite oder wie sieht die Konstellation aus

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 23:48:55 via App

Du kannst dich einfach alle Links erlauben die innerhalb dieser Kleinanzeigen seite oder nicht?

Ansonsten sind ja alle PDFs von hier
https://lafa-kleinanzeigen.de/oc-content/plugins/printpdf/download.php?item=79
nur mit anderer ID.

Damit müsstest du das hinbekommen

— geändert am 15.04.2020, 23:50:59

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 23:52:53 via Website

ja nur die id ändert sich immer und nun wie stelle ich das an.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

15.04.2020, 23:54:25 via App

Was macht deine App genau? Einfach die Webseite anzeigen?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

15.04.2020, 23:59:27 via Website

ja die website anzeigen und auch bilder upload das habe ich auch hinbekommen das es über webview geht.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

16.04.2020, 00:22:20 via App

Dann versrehe ich nicht wo dein Problem liegt.
Das PDF ist unten verlinkt wenn jemand drauf klickt musst du dich nur den Download starten z.b. mittels Download-Manager und die Datei dann öffnen.
Die ID bzw url bekommst du als Parameter in deinem WebViewClient#shouldOverrideUrl

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 00:25:52 via Website

Wenn ich das richtig verstehe muss ich in der App ein Download Manager einbauen und das mit der id muss ich mal sehen ob ich das so hinbekomme.

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 00:36:46 via Website

Okay danke ich muss mal sehen wie ich das so eingebaut bekomme. Ich hoffe ja das es dann geht und ich das richtig verstanden habe.

Hilfreich?
Pascal P.
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

16.04.2020, 08:24:33 via Website

Ja das sollte gehen.
Ansonsten postest du deinen Code, dann lässt sich einfacher feststellen woran es liegt

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 17:44:15 via Website

So hier der Code denn es will nicht so wie ich es will.
package com.example.andreasvoigt.lafa_app;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

/*-- CUSTOMIZE --*/
/*-- you can customize these options for your convenience --*/
private static String webview_url   = "https://lafa-kleinanzeigen.de";    // web address or local file location you want to open in webview
private static String file_type     = "image/*";    // file types to be allowed for upload
private boolean multiple_files      = true;         // allowing multiple file upload

/*-- MAIN VARIABLES --*/
WebView webView;

private static final String TAG = MainActivity.class.getSimpleName();

private String cam_file_data = null;        // for storing camera file information
private ValueCallback<Uri> file_data;       // data/header received after file selection
private ValueCallback<Uri[]> file_path;     // received file(s) temp. location

private final static int file_req_code = 1;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
    super.onActivityResult(requestCode, resultCode, intent);
    if(Build.VERSION.SDK_INT >= 21){
        Uri[] results = null;

        /*-- if file request cancelled; exited camera. we need to send null value to make future attempts workable --*/
        if (resultCode == Activity.RESULT_CANCELED) {
            if (requestCode == file_req_code) {
                file_path.onReceiveValue(null);
                return;
            }
        }

        /*-- continue if response is positive --*/
        if(resultCode== Activity.RESULT_OK){
            if(requestCode == file_req_code){
                if(null == file_path){
                    return;
                }

                ClipData clipData;
                String stringData;
                try {
                    clipData = intent.getClipData();
                    stringData = intent.getDataString();
                }catch (Exception e){
                    clipData = null;
                    stringData = null;
                }

                if (clipData == null && stringData == null && cam_file_data != null) {
                    results = new Uri[]{Uri.parse(cam_file_data)};
                }else{
                    if (clipData != null) { // checking if multiple files selected or not
                        final int numSelectedFiles = clipData.getItemCount();
                        results = new Uri[numSelectedFiles];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            results[i] = clipData.getItemAt(i).getUri();
                        }
                    } else {
                        results = new Uri[]{Uri.parse(stringData)};
                    }
                }
            }
        }
        file_path.onReceiveValue(results);
        file_path = null;
    }else{
        if(requestCode == file_req_code){
            if(null == file_data) return;
            Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
            file_data.onReceiveValue(result);
            file_data = null;
        }
    }
}

@SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    webView = (WebView) findViewById(R.id.webview);
    assert webView != null;
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setAllowFileAccess(true);

    if(Build.VERSION.SDK_INT >= 21){
        webSettings.setMixedContentMode(0);
        webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }else if(Build.VERSION.SDK_INT >= 19){
        webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }else {
        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    webView.setWebViewClient(new Callback());
    webView.loadUrl(webview_url);
    webView.setWebChromeClient(new WebChromeClient() {

        /*--
        openFileChooser is not a public Android API and has never been part of the SDK.
        handling input[type="file"] requests for android API 16+; I've removed support below API 21 as it was failing to work along with latest APIs.
        --*/
    /*    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            file_data = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType(file_type);
            if (multiple_files) {
                i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            }
            startActivityForResult(Intent.createChooser(i, "File Chooser"), file_req_code);
        }
    */
        /*-- handling input[type="file"] requests for android API 21+ --*/
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {

            if(file_permission() && Build.VERSION.SDK_INT >= 21) {
                file_path = filePathCallback;
                Intent takePictureIntent = null;
                Intent takeVideoIntent = null;

                boolean includeVideo = false;
                boolean includePhoto = false;

                /*-- checking the accept parameter to determine which intent(s) to include --*/
                paramCheck:
                for (String acceptTypes : fileChooserParams.getAcceptTypes()) {
                    String[] splitTypes = acceptTypes.split(", ?+"); // although it's an array, it still seems to be the whole value; split it out into chunks so that we can detect multiple values
                    for (String acceptType : splitTypes) {
                        switch (acceptType) {
                            case "*/*":
                                includePhoto = true;
                                includeVideo = true;
                                break paramCheck;
                            case "image/*":
                                includePhoto = true;
                                break;
                            case "video/*":
                                includeVideo = true;
                                break;
                        }
                    }
                }

                if (fileChooserParams.getAcceptTypes().length == 0) {   //no `accept` parameter was specified, allow both photo and video
                    includePhoto = true;
                    includeVideo = true;
                }

                if (includePhoto) {
                    takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
                        File photoFile = null;
                        try {
                            photoFile = create_image();
                            takePictureIntent.putExtra("PhotoPath", cam_file_data);
                        } catch (IOException ex) {
                            Log.e(TAG, "Image file creation failed", ex);
                        }
                        if (photoFile != null) {
                            cam_file_data = "file:" + photoFile.getAbsolutePath();
                            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                        } else {
                            cam_file_data = null;
                            takePictureIntent = null;
                        }
                    }
                }

                if (includeVideo) {
                    takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                    if (takeVideoIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
                        File videoFile = null;
                        try {
                            videoFile = create_video();
                        } catch (IOException ex) {
                            Log.e(TAG, "Video file creation failed", ex);
                        }
                        if (videoFile != null) {
                            cam_file_data = "file:" + videoFile.getAbsolutePath();
                            takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(videoFile));
                        } else {
                            cam_file_data = null;
                            takeVideoIntent = null;
                        }
                    }
                }

                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType(file_type);
                if (multiple_files) {
                    contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                }

                Intent[] intentArray;
                if (takePictureIntent != null && takeVideoIntent != null) {
                    intentArray = new Intent[]{takePictureIntent, takeVideoIntent};
                } else if (takePictureIntent != null) {
                    intentArray = new Intent[]{takePictureIntent};
                } else if (takeVideoIntent != null) {
                    intentArray = new Intent[]{takeVideoIntent};
                } else {
                    intentArray = new Intent[0];
                }

                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "File chooser");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
                startActivityForResult(chooserIntent, file_req_code);
                return true;
            } else {
                return false;
            }
        }
    });
}

/*-- callback reporting if error occurs --*/
public class Callback extends WebViewClient {
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
        Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
    }
}

/*-- checking and asking for required file permissions --*/
public boolean file_permission(){
    if(Build.VERSION.SDK_INT >=23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
        return false;
    }else{
        return true;
    }
}

/*-- creating new image file here --*/
private File create_image() throws IOException{
    @SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "img_"+timeStamp+"_";
    File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(imageFileName,".jpg",storageDir);
}

/*-- creating new video file here --*/
private File create_video() throws IOException {
    @SuppressLint("SimpleDateFormat")
    String file_name    = new SimpleDateFormat("yyyy_mm_ss").format(new Date());
    String new_name     = "file_"+file_name+"_";
    File sd_directory   = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(new_name, ".3gp", sd_directory);
}
public boolean shouldOverrideUrlLoading(webView view, String url) {
    if (url.endsWith(".pdf")) { //or whatever other extension
        //Prompt user for action (save or view)
    }
    return false;
}
/*-- back/down key handling --*/
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event){
    if(event.getAction() == KeyEvent.ACTION_DOWN){
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (webView.canGoBack()) {
                webView.goBack();
            } else {
                finish();
            }
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public void onConfigurationChanged(Configuration newConfig){
    super.onConfigurationChanged(newConfig);
}

}

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

16.04.2020, 19:26:04 via Website

Vielleicht musst du auch verstehen was dein Code macht und nicht einfach nur wild Code kopieren.
Entweder von hier:
https://forums.asp.net/t/2164510.aspx?Print+Button+from+Asp+net+to+Android+Webview
oder
https://github.com/mgks/Os-FileUp/blob/master/app/src/main/java/mgks/os/fileup/MainActivity.java
kopiert..

Du hast hier viel zu viele Dinge drin die du gar nicht brauchst...

Versuche es mit einem einfachen WebView beispiel und dann den WebView Client mit rein.
Hast du dir meine Links überhaupt durchgelesen?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 20:10:26 via Website

ja habe es mir durchgelesen die links. Ja einige sachen habe ich deswegen weil auf der website ja auch bilder upload sonst nicht geht.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

16.04.2020, 20:45:14 via Website

Hmm ok, aber wirklich strukturiert ist dein Code nicht.
Was spricht eigentlich gegen einen Link auf dem Startbildschirm anstatt einer App?

Hier mal was für die shouldOverrideUrl:

 @Override
            public boolean shouldOverrideUrlLoading (WebView view,
                                                    WebResourceRequest webRequest){
                if(webRequest.getUrl().toString().contains("https://lafa-kleinanzeigen.de/oc-content/plugins/printpdf/download.php")){
                    DownloadManager.Request request=new DownloadManager.Request(webRequest.getUrl())
                            .setTitle("PDF laden")// Title of the Download Notification
                            .setDescription("Downloading")// Description of the Download Notification
                            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);// Visibility of the download Notification

                    DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                   final long downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
                    handleFinishedReceiver(downloadID);

                    return false;
                }

                return false;
            }

Und der "finish" Receiver:

private void handleFinishedReceiver(final long downloadID) {
        BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
           @Override
           public void onReceive(Context context, Intent intent) {
               //Fetching the download id received with the broadcast
               long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
               DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
               //Checking if the received broadcast is for our enqueued download by matching download id
               if (downloadID == id) {
                   Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();

                   DownloadManager.Query q = new DownloadManager.Query();
                   q.setFilterById(id);
                   Cursor c = downloadManager.query(q);

                   if (c.moveToFirst()) {
                       int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                       if (status == DownloadManager.STATUS_SUCCESSFUL) {

                           String downloadFilePath = null;
                           String downloadFileLocalUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                           if (downloadFileLocalUri != null) {
                               File mFile = new File(Uri.parse(downloadFileLocalUri).getPath());
                                downloadFilePath = mFile.getAbsolutePath();
                               Toast.makeText(MainActivity.this, downloadFilePath, Toast.LENGTH_SHORT).show();
                           }



                       }
                   }
                   c.close();

               }
           }
       };
        registerReceiver(onDownloadComplete, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

Im Prinzip funktioniert dass.
Berechtigungen um Dateien zu schreiben und das PDF danach öffnen ist deine Sache.
Wobei evtl das öffnen von Chome o.ä. einfacher wäre weil dann sparst du dir den ganzen Code für den Download...

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 20:53:45 via Website

Na ja meine Kundschaft möchte das ganze als App, da ich ja ein Laden habe. Aber danke werde das Morgen testen und schauen wie ich das einbaue. Danke dir erstmal.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.527

16.04.2020, 21:20:10 via Website

Das mit deiner Kundschaft mag schon so sein.
Nur als richtig app würde ich das was du da machst auch nicht bezeichnen.

Die meisten werden merken das es eigentlich eine Webseite ist und sie auch gleich mit dem Browser zugreifen könnten.

Also eigentlich eine billige App.
Bin gespannt was dazu deine Kunden sagen werden.

Von eine App erwartet der User eigentlich was anders als nur eine Kopie der Webseite. In App form.

Musste ich hier einfach mal sagen.

— geändert am 16.04.2020, 21:22:08

Hilfreich?
Pascal P.
Kommentieren
heyhey83
  • Forum-Beiträge: 51

16.04.2020, 21:29:21 via Website

Ja das ist ja okay wenn du das sagst soweit geht das ja vorerst und ich werde mir noch ein Entwickler suchen der das dann mit mir zusammen macht also eine richtige App.

Hilfreich?
Kommentieren