Android WebView

Este guia apresenta como integrar o smart checkout em aplicações Android nativas utilizando WebView, permitindo incorporar a experiência de pagamento diretamente no aplicativo.

O objetivo é fornecer uma implementação estável, segura e compatível com os principais métodos de pagamento suportados.


📋 Requisitos mínimos

Android

  • minSdkVersion: 21 (Android 5.0)
  • targetSdkVersion: 33 (Android 13)
  • compileSdkVersion: 33

Dependências Gradle

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

⚙️ Configuração do projeto

build.gradle (Projeto)

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.2'
    }
}

build.gradle (App)

android {
    namespace 'com.exemplo.webview'
    compileSdkVersion 33
    
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 33
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

🔐 Permissões necessárias

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Permissões Básicas -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <!-- Permissões para Download -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:usesCleartextTraffic="true"
        android:requestLegacyExternalStorage="true">
        
        <!-- FileProvider para Downloads -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest>

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="." />
    <external-cache-path name="external_cache" path="." />
    <cache-path name="cache" path="." />
    <files-path name="files" path="." />
</paths>

🧩 Implementação da WebView

Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/urlEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Digite a URL"
            android:inputType="textUri"
            android:padding="8dp" />

        <Button
            android:id="@+id/loadButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:text="Carregar" />

    </LinearLayout>

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_marginTop="16dp" />

</LinearLayout>

Configuração da WebView (MainActivity.java)

public class MainActivity extends AppCompatActivity {
    private WebView webView;

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

        // Inicializa a WebView
        webView = findViewById(R.id.webView);

        // Configurações Básicas
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setLoadWithOverviewMode(true);
        webSettings.setUseWideViewPort(true);
        
        // Configurações Adicionais
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setDatabaseEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

        // Habilita Debugging
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        // Configura o WebViewClient
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, 
                    WebResourceError error) {
                // Tratamento de erros
            }
        });

        // Carrega a URL do Smart Checkout
        webView.loadUrl("https://domain.com");
    }
}

👉 Recursos Adicionais

Tratamento de permissões em runtime

private void checkAndRequestPermissions() {
    if (ContextCompat.checkSelfPermission(this, 
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
            new String[]{
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE
            },
            PERMISSION_REQUEST_CODE);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, 
        String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permissão concedida
        } else {
            // Permissão negada
        }
    }
}

Interceptação de downloads

webView.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent, 
            String contentDisposition, String mimetype, long contentLength) {
        // Para URLs normais
        if (!url.startsWith("data:")) {
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
            request.setMimeType(mimetype);
            request.addRequestHeader("User-Agent", userAgent);
            request.setDescription("Baixando arquivo...");
            request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimetype));
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(
                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            request.setDestinationInExternalPublicDir(
                Environment.DIRECTORY_DOWNLOADS, 
                URLUtil.guessFileName(url, contentDisposition, mimetype));

            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            dm.enqueue(request);
        } else {
            // Para data URLs (base64)
            handleBase64Download(url, mimetype);
        }
    }
});

⚠️ Problemas comuns e soluções

ERR_CLEARTEXT_NOT_PERMITTED

  • Adicione android:usesCleartextTraffic="true" no AndroidManifest.xml
  • Ou use HTTPS

Erro de permissão de armazenamento

  • Verifique se as permissões estão declaradas no manifest
  • Implemente a solicitação de permissão em runtime
  • Para Android 10+, use android:requestLegacyExternalStorage="true"

WebView não carrega

  • Verifique a conexão com a internet
  • Confirme se INTERNET permission está no manifest
  • Verifique se JavaScript está habilitado

Downloads não funcionam

  • Verifique permissões de armazenamento
  • Configure o FileProvider
  • Implemente DownloadListener

🧪 Debug e logs

// Habilita logs do console
webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        Log.d("WebView", consoleMessage.message());
        return true;
    }
});

// Debugging via Chrome DevTools
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);
}

✅ Boas práticas

  • Sempre usar HTTPS
  • Testar em múltiplas versões Android
  • Validar fluxo completo (Pix, cartão, etc.)
  • Monitorar logs da WebView
  • Utilizar Webhook para confirmação de pagamento (não confiar apenas na UI)

🎯 Resumo

A integração via WebView é a forma mais rápida de incorporar o smart checkout em apps Android, mantendo controle da experiência sem precisar implementar uma UI de pagamento nativa.


Did this page help you?