API جاوا اسکریپت
اپلیکیشنهایی که با Free HTML to APK ساخته میشوند یک پل بومی را با نام window.FreeApp تزریق میکنند. آن را از جاوا اسکریپت ساده، از React یا Vue یا از یک موتور بازی صدا بزنید. اگر فراخوانیها را محافظت کنید، صفحه شما در مرورگر معمولی هم کار میکند.
شروع کار
پل ممکن است کمی بعد از اجرای اسکریپتهای شما برسد، پس راهاندازی بومی را در رویداد freeappready انجام دهید و اگر window.FreeApp از قبل وجود دارد، همان لحظه هم انجام دهید. همیشه برای مرورگر یک جایگزین فراهم کنید.
function setup() { FreeApp.statusBar('#E2552A'); FreeApp.toast('Hello from Android'); } if (window.FreeApp) setup(); else window.addEventListener('freeappready', setup, { once: true }); document.querySelector('#buzz').onclick = () => window.FreeApp ? FreeApp.vibrate(40) : console.log('Not in the app');
فراخوانیهایی که مجوز میخواهند (دوربین، میکروفون، موقعیت مکانی، اعلانها) بار اول از کاربر میپرسند. مجوز مربوطه را در مرحله مجوزها سازنده روشن کنید؛ قالبها آنچه کدشان استفاده میکند را خودشان روشن میکنند.
بازخورد و رابط کاربری
FreeApp.brightness(level: number): voidاز 0.0 تا 1.0 برای این پنجره؛ مقدار منفی روشنایی سیستم را بازمیگرداند.
FreeApp.fullscreen(on: boolean): voidنوارهای سیستم را پنهان کنید (حالت فراگیر).
FreeApp.keepAwake(on: boolean): voidصفحه را روشن نگه دارید.
FreeApp.notify(title: string, body?: string): voidاعلان محلی فوری (در Android 13 به بالا مجوز میخواهد).
FreeApp.orientation(value: 'portrait' | 'landscape' | 'sensor_portrait' | 'sensor_landscape' | 'sensor' | 'unspecified'): voidFreeApp.print(): voidچاپ / ذخیره صفحه بهصورت PDF.
FreeApp.scheduleNotification(title: string, body: string, delayMs: number, opts?: {id?: number, url?: string, repeatMs?: number, exact?: boolean}): numberشناسه را برمیگرداند.
FreeApp.speak(text: string, lang?: string): voidتبدیل متن به گفتار بومی، زبان مثل 'en-US'.
FreeApp.statusBar(hexColor: string): voidمثلاً '#2563EB'.
FreeApp.stopSpeaking(): voidFreeApp.toast(message: string): voidتوست بومی کوتاه.
FreeApp.vibrate(ms?: number | number[]): voidیک لرزش یکباره (پیشفرض 50 میلیثانیه) یا الگوی [off, on, off, on…].
دوربین و اسکن
FreeApp.camera.capture(opts?: {maxSize?: number, quality?: number, mirror?: boolean}): Promise<{dataUrl, facing}>عکس ثابت از پیشنمایش در حال اجرا.
FreeApp.camera.start(opts?: {facing?: 'back' | 'front', element?: string | Element /* place the preview over this element */, behind?: boolean /* draw under a transparent page so HTML controls float on top */}): Promise<{facing}>FreeApp.camera.switch(): Promise<{facing}>; FreeApp.camera.torch(on: boolean): boolean; FreeApp.camera.stop(): void; FreeApp.camera.isOpen(): booleanFreeApp.compressImage(dataUrl: string, opts?: {maxSize?: number, quality?: number}): Promise<{dataUrl, width, height, bytes}>بومی و سریع روی گوشیهای ضعیف.
FreeApp.saveToGallery(dataUrl: string, fileName?: string): Promise<{uri}>یک تصویر را در Photos ذخیره میکند.
FreeApp.scanCode(opts?: {formats?: string[] /* e.g. ['QR_CODE','EAN_13','CODE_128'] */, facing?: 'back' | 'front'}): Promise<{text, format}>اسکنر بومی تمامصفحه QR / بارکد با چراغقوه؛ با 'cancelled' رد میشود.
FreeApp.torch(on: boolean): booleanچراغقوه؛ اگر فلاش نباشد false برمیگرداند.
موقعیت مکانی و حسگرها
FreeApp.address(lat: number, lng: number): Promise<{address, city, country, countryCode, postalCode, street}>FreeApp.compass(cb: (d: {heading: number /* degrees */, pitch: number, roll: number}) => void): (() => void) | nullیک تابع توقف برمیگرداند.
FreeApp.location(opts?: {maxAge?: number}): Promise<{lat, lng, accuracy, altitude, speed, provider, time, fromLastKnown}>FreeApp.maps(query: string): voidیک مکان یا «lat,lng» را در اپلیکیشن نقشه باز کنید.
FreeApp.sensors.start(type: 'accelerometer' | 'gyroscope' | 'magnetometer' | 'light' | 'proximity' | 'pressure' | 'gravity' | 'linear_acceleration' | 'rotation' | 'humidity' | 'temperature' | 'steps' | 'step_detector', cb: (d: {type, values: number[], x, y, z, accuracy, t}) => void, intervalMs?: number): (() => void) | nullیک تابع توقف برمیگرداند، یا اگر در دسترس نباشد null.
FreeApp.sensors.stop(type: string): voidFreeApp.watchLocation(cb: (p) => void, opts?: {interval?: number, distance?: number}): () => voidیک تابع توقف برمیگرداند.
دستگاه و اپلیکیشن
FreeApp.app(): {packageName, versionName, versionCode, name, firstInstall}FreeApp.battery(): {level: number /* 0-100 */, charging: boolean}FreeApp.biometric(title: string, subtitle?: string): Promise<boolean>قفلگشایی با اثر انگشت / چهره.
FreeApp.device(): {manufacturer, model, brand, androidVersion, sdkInt, language, screenWidth, screenHeight, density, isTablet, darkMode}FreeApp.launchUrl(): string | nullلینک عمیقی که اپلیکیشن را باز کرد.
FreeApp.network(): 'wifi' | 'cellular' | 'ethernet' | 'vpn' | 'other' | 'none' | 'unknown'FreeApp.on('deeplink', (d: {url}) => void): () => voidلینکهایی که هنگام اجرای اپلیکیشن باز شدند.
FreeApp.online(): booleanفایلها، اشتراکگذاری و ذخیرهسازی
FreeApp.copy(text: string): voidکپی در کلیپبورد.
FreeApp.open(url: string): voidدر مرورگر / اپلیکیشن بیرونی باز کنید.
FreeApp.paste(): stringمتن کلیپبورد را بخوانید.
FreeApp.pickFile(opts?: {accept?: string[], multiple?: boolean}): Promise<{name, mime, size, dataUrl}>FreeApp.saveFile(name: string, mime: string, data: string /* base64 or data: URL */ | Blob): Promise<boolean>در Downloads ذخیره میکند؛ FreeApp.on('saved', d => …) مقدار {name, ok, location} را میدهد.
FreeApp.store.get(key: string): any | nullFreeApp.store.set(key: string, value: any): voidکلید/مقدار بومی ماندگار (JSON).
NFC
FreeApp.nfc.read(): Promise<{tagId, techs: string[], writable, maxSize, records: Array<{type: "text" | "uri" | "mime" | "unknown", value, mime?, lang?}>}>منتظر یک تگ میماند؛ FreeApp.nfc.stop() لغو میکند.
FreeApp.nfc.status(): 'ready' | 'disabled' | 'unsupported' | 'not_enabled_in_app'FreeApp.nfc.write(records: string | Array<{type: 'text' | 'uri' | 'mime', value: string, mime?: string}>): Promise<{written}>مجوزها
FreeApp.hasPermission(name: string): booleanFreeApp.openSettings(): voidصفحه تنظیمات سیستم این اپلیکیشن را باز میکند.
FreeApp.permissionStatus(name: 'camera' | 'microphone' | 'location' | 'notifications' | 'activity'): 'granted' | 'prompt' | 'blocked' | 'unavailable'FreeApp.requestPermission(name: 'camera' | 'microphone' | 'location' | 'notifications'): Promise<boolean>FreeApp.requestPermissions(names: string[]): Promise<{[name]: boolean}>تبلیغات
وقتی AdMob در سازنده روشن باشد در دسترس است. در حالت آزمایشی، تبلیغات آزمایشی Google نمایش داده میشود.
FreeApp.ads.loadBanner(unit?: string, position?: 'top' | 'bottom'): voidیک بنر را بارگذاری و نمایش میدهد. بدون آرگومان از واحد و موقعیتی که در سازنده تنظیم شده استفاده میکند.
FreeApp.ads.showBanner(position?) / hideBanner() / isBannerLoaded()بنر را نشان دهید، پنهان کنید یا بررسی کنید.
FreeApp.ads.loadInterstitial(unit?) / showInterstitial() / isInterstitialLoaded()تبلیغات تمامصفحه بین صفحهها. بین تبلیغات تمامصفحه حداقل فاصله اعمال میشود.
FreeApp.ads.loadRewarded(unit?) / isRewardedLoaded()یک تبلیغ پاداشدار را از قبل بارگذاری کنید.
FreeApp.ads.showRewarded(): Promise<{ok, amount, type}>یک تبلیغ پاداشدار نشان میدهد؛ وقتی کاربر پاداش را گرفت موفق میشود و اگر زودتر ببندد رد میشود.
FreeApp.ads.privacyOptionsRequired(): boolean / showPrivacyOptions()به کاربران اجازه میدهد انتخابهای رضایت خود را تغییر دهند (در برخی مناطق الزامی است).
FreeApp.ads.adapterStatus(): {[network]: {installed, configured, ready, description, latencyMs}}با میانجیگری: کدام شبکههای همکار داخل اپلیکیشن هستند و کدامها در حساب AdMob شما راهاندازی شدهاند.
FreeApp.ads.openAdInspector(): voidAd Inspector گوگل را روی دستگاههای آزمایشی باز میکند.
FreeApp.ads.on(cb: (event) => void): () => voidرویدادهای تبلیغاتی مثل initialized، bannerLoaded، interstitialDismissed یا rewardedFailed. یک تابع لغو اشتراک برمیگرداند.
با خرید «حذف تبلیغات»، تبلیغات بنری و تمامصفحه متوقف میشوند و رویداد adFree اجرا میشود. تبلیغات پاداشدار همچنان کار میکنند، چون کاربران خودشان تماشای آنها را انتخاب میکنند.
خرید درونبرنامهای
وقتی «خریدها» در سازنده روشن باشد در دسترس است. محصولات یکباره، محصولات مصرفی مثل سکه، و اشتراکها را از طریق حساب Google Play خودتان بفروشید. ابتدا محصولات را با همان شناسهها در Play Console بسازید. خریدها در نسخهای کار میکنند که از Google Play نصب شده باشد، پس با یک ترک تست و یک تستکننده لایسنس آزمایش کنید.
const billing = window.FreeApp && FreeApp.billing; if (billing && billing.isOwned('pro_unlock')) unlockPro(); // Unlock in the purchase event: it also arrives for purchases finished while the app was closed. billing && billing.on(e => { if (e.event === 'purchase' && e.id === 'pro_unlock') unlockPro(); }); buyButton.onclick = async () => { try { await billing.buy('pro_unlock'); } catch (err) { if (err.code === 'pending') show('Payment pending'); else if (err.code !== 'cancelled') show('Purchase failed'); } };
FreeApp.billing.products(ids: string[]): Promise<Product[]>جزئیات زنده Google Play برای محصولات شما: عنوان، قیمت محلی، واحد پول، و برای اشتراکها دوره صورتحساب و پیشنهادها. شناسههایی که Play نمیشناسد کنار گذاشته میشوند.
FreeApp.billing.buy(id: string, opts?: {offer?: string}): Promise<Purchase>صفحه پرداخت Google Play را باز میکند. برای اشتراک، offer یک طرح پایه یا شناسه پیشنهاد را انتخاب میکند. در صورت خطا reject میشود و کد خطا یکی از cancelled، pending، not_found، unavailable، busy، network یا developer_error است.
FreeApp.billing.owned(): string[] / isOwned(id): booleanچیزهایی که کاربر دارد، ذخیرهشده روی گوشی، پس فوراً و حتی آفلاین پاسخ میدهد. هنگام شروع از آن استفاده کنید تا قابلیتهای پولی را باز کنید.
FreeApp.billing.restore(): Promise<{purchases, owned}>دوباره از Google Play همه چیزهایی را که کاربر دارد میپرسد، برای دکمه «بازیابی خریدها».
FreeApp.billing.consume(idOrToken: string): Promiseیک محصول یکباره را مصرف میکند تا بتوان دوباره آن را خرید. محصولاتی که در سازنده بهعنوان مصرفی فهرست شدهاند، خودکار مصرف میشوند.
FreeApp.billing.isAdFree(): booleantrue وقتی کاربر یکی از محصولات «حذف تبلیغات» تنظیمشده در سازنده را داشته باشد. در این صورت اپلیکیشن خودش تبلیغات بنری و تمامصفحه را متوقف میکند.
FreeApp.billing.manageSubscriptions(id?: string): voidصفحه اشتراکهای Google Play را باز میکند، جایی که کاربران طرح خود را لغو یا عوض میکنند.
FreeApp.billing.on(cb: (event) => void): () => voidرویدادهای خرید: purchase (اینجا باز کنید)، pending، owned (فهرست موارد خریداریشده تغییر کرد: یک خرید، بازپرداخت یا اشتراک منقضیشده)، failed و unavailable. یک تابع لغو اشتراک برمیگرداند.
لایه سازگاری
صفحههایی که برای ابزارهای دیگر تبدیل HTML به APK نوشته شدهاند و window.AndroidAPI را صدا میزنند همچنان کار میکنند: نام متدها، شناسههای callback و نام رویدادها یکسان پشتیبانی میشوند و فراخوانیهای تبلیغاتی در اپلیکیشنهای بدون تبلیغ بیخطر و بیاثرند.