Step-by-step টিউটোরিয়াল — আপনার টিম সহজেই কপি করে অ্যাপ বানাতে পারবে।
TextView সরিয়ে নিচের WebView কোড paste করুন:
<WebView android:id="@+id/WebviewID" android:layout_width="match_parent" android:layout_height="match_parent"/>
public class MainActivity extends AppCompatActivity { এই লাইনের পরে paste করুন। লাল রঙ দেখালে Alt + Enter চাপুন।
WebView webView; ProgressDialog progressDialog;
setContentView(R.layout.activity_main); এর পরে paste করুন
webView = (WebView) findViewById(R.id.WebviewID); webView.loadUrl("https://yourwebsite.com/"); // ← আপনার URL দিন WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(false); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); webSettings.setDomStorageEnabled(true); webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); webView.setScrollbarFadingEnabled(true); progressDialog = new ProgressDialog(this); progressDialog.setMessage("Loading Please Wait..."); webView.setWebViewClient(new WebViewClient()); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { progressDialog.show(); if (newProgress == 100) { progressDialog.dismiss(); } super.onProgressChanged(view, newProgress); } }); // Back Button @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } }
<application ট্যাগের আগে paste করুন
<uses-permission android:name="android.permission.INTERNET"/>
res → Drawable ফোল্ডারে paste করুন। Manifest এ logo সিলেক্ট করুন।res → values → themes.xml এ দুটো জায়গায় DarkActionBar থেকে NoActionBar করুন।Menu → Build → Generate Signed App<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/WebviewID" android:layout_width="match_parent" android:layout_height="match_parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
com.imanteams.demando_restaurant_partner.provider — এটি আপনার App ID দিয়ে পরিবর্তন করুন
import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; 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.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity { WebView webView; ValueCallback<Uri[]> filePathCallback; Uri cameraImageUri; ActivityResultLauncher<Intent> fileChooserLauncher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestCameraPermission(); webView = findViewById(R.id.WebviewID); webView.loadUrl("https://yourwebsite.com/"); // ← URL পরিবর্তন করুন WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); settings.setAllowFileAccess(true); settings.setAllowContentAccess(true); settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); fileChooserLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { Uri[] results = null; if (result.getResultCode() == RESULT_OK) { if (result.getData() == null) { results = new Uri[]{cameraImageUri}; } else { results = WebChromeClient.FileChooserParams.parseResult( result.getResultCode(), result.getData()); } } if (filePathCallback != null) { filePathCallback.onReceiveValue(results); filePathCallback = null; } }); webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { MainActivity.this.filePathCallback = filePathCallback; Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraIntent.resolveActivity(getPackageManager()) != null) { try { File photoFile = createImageFile(); cameraImageUri = FileProvider.getUriForFile( MainActivity.this, "YOUR_APP_ID.provider", // ← পরিবর্তন করুন photoFile); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri); } catch (IOException e) { Toast.makeText(MainActivity.this, "Camera error", Toast.LENGTH_SHORT).show(); } } Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); galleryIntent.addCategory(Intent.CATEGORY_OPENABLE); galleryIntent.setType("image/*"); Intent chooser = new Intent(Intent.ACTION_CHOOSER); chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent); chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{cameraIntent}); fileChooserLauncher.launch(chooser); return true; } }); } private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile("IMG_" + timeStamp, ".jpg", storageDir); } private void requestCameraPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.CAMERA}, 100); } } } @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } }
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="images" path="Pictures/" /> </paths>
<!-- application এর আগে --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.CAMERA"/> <!-- activity এর আগে, application এর ভেতরে --> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
// WebSettings এ যোগ করুন webSettings.setGeolocationEnabled(true); // WebChromeClient এর ভেতরে @Override public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); // ✅ অনুমতি দিন } // Permission Request (onCreate এ) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_PERMISSIONS); }
Project → app → src ফোল্ডারে paste করুনid 'com.google.gms.google-services' version '4.4.4' apply false
// plugins এর ভেতরে id 'com.google.gms.google-services' // dependencies এর ভেতরে implementation platform('com.google.firebase:firebase-bom:34.12.0') implementation 'com.google.firebase:firebase-analytics' implementation 'com.google.firebase:firebase-messaging:23.0.0'
import android.app.NotificationChannel; import android.app.NotificationManager; import android.os.Build; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; public class MyFirebaseService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { String title = remoteMessage.getNotification().getTitle(); String body = remoteMessage.getNotification().getBody(); showNotification(title, body); } private void showNotification(String title, String message) { String channelId = "CHANNEL_ID"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( channelId, "Default Channel", NotificationManager.IMPORTANCE_HIGH); getSystemService(NotificationManager.class).createNotificationChannel(channel); } NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.logo) .setContentTitle(title) .setContentText(message) .setPriority(NotificationCompat.PRIORITY_HIGH); NotificationManagerCompat.from(this).notify(1, builder.build()); } }
user টেবিলে token column যোগ করুন — type: longtext
<?php include("dbcon.php"); if(isset($_REQUEST['phone']) AND isset($_REQUEST['token'])){ $phone = mysqli_real_escape_string($con, $_REQUEST['phone']); $token = mysqli_real_escape_string($con, $_REQUEST['token']); mysqli_query($con, "UPDATE `user` SET `token`='$token' WHERE `phone`='$phone'"); } ?>
app → src → main → assets ফোল্ডারে রাখুন। ফোল্ডার না থাকলে তৈরি করুন।
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>No Internet</title> <style> body { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; background: #f5f5f5; font-family: 'Roboto', Arial, sans-serif; text-align: center; padding: 20px; } .icon { font-size: 70px; margin-bottom: 15px; animation: float 3s ease-in-out infinite; } h2 { color: #e74c3c; font-size: 24px; margin-bottom: 10px; } p { color: #666; font-size: 16px; margin-bottom: 30px; } @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } </style> </head> <body> <div class="icon">📡❌</div> <h2>No Internet Connection</h2> <p>Please check your internet connection and try again.</p> </body> </html>
webView.loadUrl("file:///android_asset/no_internet.html");
loadUrl(...)