قابلیتهای Wi-Fi Aware به دستگاههای دارای Android نسخه ۸.۰ (سطح API ۲۶) و بالاتر امکان میدهد بدون هیچ نوع اتصال دیگری بین آنها، مستقیماً یکدیگر را پیدا کنند و به هم متصل شوند. Wi-Fi Aware با نام شبکه اتصال مجاورتی (NAN) نیز شناخته میشود.
شبکهسازی Wi-Fi Aware با تشکیل خوشههایی با دستگاههای مجاور یا با ایجاد خوشه جدید درصورتیکه دستگاه اولین دستگاه در منطقه باشد کار میکند. این رفتار خوشهبندی برای کل دستگاه اعمال میشود و توسط سرویس سیستم Wi-Fi Aware مدیریت میشود؛ برنامهها هیچ کنترلی بر رفتار خوشهبندی ندارند. برنامهها از Wi-Fi Aware APIs برای صحبت با سرویس سیستم Wi-Fi Aware استفاده میکنند که سختافزار Wi-Fi Aware را در دستگاه مدیریت میکند.
«میاناهای برنامهسازی کاربردی» Wi-Fi Aware به برنامهها اجازه میدهند عملیات زیر را انجام دهند:
شناسایی دستگاههای دیگر: این میانای برنامهسازی کاربردی سازوکاری برای پیدا کردن دستگاههای اطراف دارد. این فرایند زمانی شروع میشود که یک دستگاه یک یا چند سرویس قابلکشف را منتشر کند. سپس، وقتی دستگاهی در یک یا چند سرویس مشترک میشود و وارد محدوده Wi-Fi ناشر میشود، مشترک اعلانی دریافت میکند که ناشر منطبقی پیدا شده است. پساز اینکه مشترک ناشر را پیدا کرد، میتواند پیام کوتاهی ارسال کند یا اتصال شبکهای با دستگاه پیداشده برقرار کند. دستگاهها میتوانند بهطور همزمان هم ناشر و هم مشترک باشند.
ایجاد اتصال شبکه: پساز اینکه دو دستگاه یکدیگر را شناسایی کردند، میتوانند اتصال شبکه Wi-Fi Aware دوطرفه بدون نقطه دسترسی ایجاد کنند.
اتصالهای شبکه Wi-Fi Aware از نرخهای توان عملیاتی بالاتری در فواصل طولانیتر نسبت به اتصالهای بلوتوث پشتیبانی میکنند. این نوع اتصالها برای برنامههایی که حجم زیادی از داده را بین کاربران همرسانی میکنند، مانند برنامههای همرسانی عکس، مفید است.
بهبودهای Android 13 (میانای برنامهسازی کاربردی سطح ۳۳)
در دستگاههایی که Android 13 (سطح میانای برنامهسازی کاربردی ۳۳) و بالاتر را اجرا میکنند و از حالت ارتباط فوری پشتیبانی میکنند، برنامهها میتوانند از روشهای PublishConfig.Builder.setInstantCommunicationModeEnabled() و SubscribeConfig.Builder.setInstantCommunicationModeEnabled() برای فعال یا غیرفعال کردن حالت ارتباط فوری برای جلسه کاوش ناشر یا مشترک استفاده کنند. حالت ارتباط فوری تبادل پیام، کشف سرویس، و هرگونه راهاندازی مسیر داده را بهعنوان بخشی از جلسه کشف ناشر یا مشترک تسریع میکند. برای تعیین اینکه آیا دستگاهی از حالت ارتباط فوری پشتیبانی میکند یا نه، از روش isInstantCommunicationModeSupported() استفاده کنید.
بهبودهای Android 12 (سطح میانای برنامهسازی کاربردی ۳۱)
Android 12 (سطح میانای برنامهسازی کاربردی ۳۱) چند بهبود به Wi-Fi Aware اضافه میکند:
- در دستگاههای دارای Android 12 (سطح میانای برنامهسازی کاربردی ۳۱) یا بالاتر، میتوانید از
onServiceLost()فراخوانی برگشتی استفاده کنید تا وقتی برنامهتان سرویس کشفشدهای را بهدلیل توقف سرویس یا خارج شدن از محدوده ازدست میدهد، هشدار دریافت کنید. - راهاندازی مسیرهای داده Wi-Fi Aware سادهتر شده است. نسخههای قبلی از پیامرسانی L2 برای ارائه نشانی MAC راهانداز استفاده میکردند که باعث تأخیر میشد. در دستگاههای دارای Android 12 و بالاتر، پاسخدهنده (سرور) را میتوان بهگونهای پیکربندی کرد که هر همتایی را بپذیرد—یعنی نیازی نیست که ازقبل نشانی MAC آغازگر را بداند. این کار راهاندازی مسیر داده را سرعت میبخشد و چندین پیوند نقطه به نقطه را تنها با یک درخواست شبکه فعال میکند.
- برنامههایی که در Android نسخه ۱۲ یا بالاتر اجرا میشوند میتوانند از روش
WifiAwareManager.getAvailableAwareResources()برای دریافت تعداد مسیرهای داده دردسترس کنونی، جلسههای انتشار، و جلسههای اشتراک استفاده کنند. این کار میتواند به برنامه کمک کند تا تشخیص دهد آیا منابع کافی برای اجرای عملکرد موردنظر وجود دارد یا نه.
راهاندازی اولیه
برای راهاندازی برنامهتان جهت استفاده از کاوش و شبکهسازی Wi-Fi Aware، مراحل زیر را انجام دهید:
اجازههای زیر را در مانیفست برنامهتان درخواست کنید:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- If your app targets Android 13 (API level 33) or higher, you must declare the NEARBY_WIFI_DEVICES permission. --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" <!-- If your app derives location information from Wi-Fi APIs, don't include the "usesPermissionFlags" attribute. --> android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" <!-- If any feature in your app relies on precise location information, don't include the "maxSdkVersion" attribute. --> android:maxSdkVersion="32" />
بررسی کنید که آیا دستگاه از Wi-Fi Aware با
PackageManagerAPI پشتیبانی میکند یا نه، همانطور که در زیر نشان داده شده است:کاتلین
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
جاوا
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
بررسی کنید آیا Wi-Fi Aware درحالحاضر دردسترس است یا نه. ممکن است Wi-Fi Aware در دستگاه وجود داشته باشد، اما ممکن است درحالحاضر دردسترس نباشد زیرا کاربر Wi-Fi یا «مکان» را غیرفعال کرده است. بسته به قابلیتهای سختافزار و سفتافزار، برخیاز دستگاهها ممکن است درصورت استفاده از Wi-Fi Direct، SoftAP، یا اینترنتبخشی، از Wi-Fi Aware پشتیبانی نکنند. برای بررسی اینکه آیا Wi-Fi Aware درحالحاضر دردسترس است یا نه،
isAvailable()را فراخوانی کنید.دردسترس بودن Wi-Fi Aware ممکن است در هر زمانی تغییر کند. برنامه شما باید
BroadcastReceiverرا برای دریافتACTION_WIFI_AWARE_STATE_CHANGEDثبت کند، که هرگاه دردسترس بودن تغییر کند ارسال میشود. وقتی برنامهتان هدف همهفرستی را دریافت میکند، باید همه جلسههای موجود را دور بیندازد (فرض کنید که سرویس Wi-Fi Aware مختل شده است)، سپس وضعیت فعلی دردسترس بودن را بررسی کند و رفتار خود را براساس آن تنظیم کند. برای مثال:کاتلین
val wifiAwareManager = context.getSystemService(Context.WIFI_AWARE_SERVICE) as WifiAwareManager? val filter = IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED) val myReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // discard current sessions if (wifiAwareManager?.isAvailable) { ... } else { ... } } } context.registerReceiver(myReceiver, filter)
جاوا
WifiAwareManager wifiAwareManager = (WifiAwareManager)context.getSystemService(Context.WIFI_AWARE_SERVICE) IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // discard current sessions if (wifiAwareManager.isAvailable()) { ... } else { ... } } }; context.registerReceiver(myReceiver, filter);
برای اطلاعات بیشتر، به همهفرستیها مراجعه کنید.
دریافت جلسه
برای شروع استفاده از Wi-Fi Aware، برنامهتان باید با فراخوانی
attach()،
WifiAwareSession را دریافت کند. این روش
کارهای زیر را انجام میدهد:
- سختافزار Wi-Fi Aware را روشن میکند.
- به خوشه Wi-Fi Aware میپیوندد یا آن را تشکیل میدهد.
- یک جلسه Wi-Fi Aware با فضای نام منحصربهفرد ایجاد میکند که بهعنوان محفظهای برای همه جلسههای کشف ایجادشده در آن عمل میکند.
اگر برنامه باموفقیت متصل شود، سیستم فراخوانی برگشتی
onAttached() را اجرا میکند.
این فراخوانی برگشتی یک شیء WifiAwareSession ارائه میدهد
که برنامهتان باید برای همه عملیاتهای جلسه بعدی استفاده کند. برنامه میتواند از
جلسه برای انتشار سرویس یا
مشترک شدن در سرویس استفاده کند.
برنامه شما باید
attach() را فقط یکبار فراخوانی کند. اگر
برنامه شما attach()
را چندین بار فراخوانی کند، برنامه برای هر فراخوانی یک جلسه متفاوت دریافت میکند که هرکدام
فضای نام خود را دارند. این کار میتواند در سناریوهای پیچیده مفید باشد، اما بهطور کلی باید از آن اجتناب شود.
انتشار سرویس
برای قابلشناسایی کردن سرویس،
روش publish() را فراخوانی کنید که
پارامترهای زیر را میگیرد:
-
PublishConfigنام سرویس و دیگر ویژگیهای پیکربندی، مثل فیلتر تطابق، را مشخص میکند. DiscoverySessionCallbackکنشهایی را که باید هنگام وقوع رویدادها اجرا شود مشخص میکند، مثلاً وقتی مشترک پیامی دریافت میکند.
مثالی در اینجا ارائه شده است:
کاتلین
val config: PublishConfig = PublishConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.publish(config, object : DiscoverySessionCallback() { override fun onPublishStarted(session: PublishDiscoverySession) { ... } override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) { ... } })
جاوا
PublishConfig config = new PublishConfig.Builder() .setServiceName(“Aware_File_Share_Service_Name”) .build(); awareSession.publish(config, new DiscoverySessionCallback() { @Override public void onPublishStarted(PublishDiscoverySession session) { ... } @Override public void onMessageReceived(PeerHandle peerHandle, byte[] message) { ... } }, null);
اگر انتشار موفقیتآمیز باشد، روش فراخوانی
onPublishStarted()
فراخوانده میشود.
پساز انتشار، وقتی دستگاههای دارای برنامههای مشترک منطبق به محدوده Wi-Fi دستگاه منتشرکننده وارد میشوند، مشترکین سرویس را پیدا میکنند. وقتی
مشترکی ناشری را پیدا میکند، ناشر
اعلان دریافت نمیکند؛ اما اگر مشترک پیامی به ناشر ارسال کند،
ناشر اعلان دریافت میکند. وقتی این اتفاق میافتد،
onMessageReceived()
روش فراخوانی نامیده میشود. میتوانید از
آرگومان PeerHandle از این روش برای
ارسال پیام به مشترک یا
ایجاد اتصال به آن استفاده کنید.
برای متوقف کردن انتشار سرویس، با
DiscoverySession.close() تماس بگیرید.
جلسههای «کاوش» با ولیشان
WifiAwareSession مرتبط هستند. اگر جلسه اصلی بسته شود، جلسههای کاوش مرتبط با آن نیز بسته میشوند. درحالیکه اشیاء دورریختهشده نیز بسته میشوند، سیستم تضمین نمیکند که جلسههای خارج از محدوده چه زمانی بسته میشوند، بنابراین توصیه میکنیم که صریحاً روشهای close() را فراخوانی کنید.
مشترک شدن در سرویس
برای مشترک شدن در سرویس،
روش subscribe() را فراخوانی کنید
که پارامترهای زیر را میگیرد:
-
SubscribeConfigنام سرویسی را که باید در آن مشترک شد و سایر ویژگیهای پیکربندی، مانند فیلتر مطابقت، را مشخص میکند. DiscoverySessionCallbackکنشهایی را که باید هنگام وقوع رویدادها اجرا شوند مشخص میکند، مثلاً وقتی ناشری کشف میشود.
مثالی در اینجا ارائه شده است:
کاتلین
val config: SubscribeConfig = SubscribeConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.subscribe(config, object : DiscoverySessionCallback() { override fun onSubscribeStarted(session: SubscribeDiscoverySession) { ... } override fun onServiceDiscovered( peerHandle: PeerHandle, serviceSpecificInfo: ByteArray, matchFilter: List<ByteArray> ) { ... } }, null)
جاوا
SubscribeConfig config = new SubscribeConfig.Builder() .setServiceName("Aware_File_Share_Service_Name") .build(); awareSession.subscribe(config, new DiscoverySessionCallback() { @Override public void onSubscribeStarted(SubscribeDiscoverySession session) { ... } @Override public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { ... } }, null);
اگر عملیات اشتراک موفقیتآمیز باشد، سیستم
onSubscribeStarted()
را در برنامهتان فراخوانی میکند. چون میتوانید از
SubscribeDiscoverySession در
فراخوانی برای برقراری ارتباط با ناشر پساز اینکه برنامهتان یکی را پیدا کرد استفاده کنید،
باید این مرجع را ذخیره کنید. هرزمان بخواهید میتوانید جلسه اشتراک را با فراخوانی
updateSubscribe()
در جلسه کاوش بهروز کنید.
در این مرحله، اشتراکتان منتظر میماند تا ناشران منطبق وارد محدوده Wi-Fi شوند. وقتی این اتفاق میافتد، سیستم روش فراخوانی
onServiceDiscovered()
را اجرا میکند. میتوانید از آرگومان PeerHandle
از این فراخوانی برگشتی برای ارسال پیام یا
ایجاد اتصال به آن ناشر استفاده کنید.
برای لغو اشتراک سرویس، با
DiscoverySession.close() تماس بگیرید.
جلسههای «کاوش» با ولیشان
WifiAwareSession مرتبط هستند. اگر جلسه اصلی بسته شود، جلسههای کاوش مرتبط با آن نیز بسته میشوند. درحالیکه اشیاء دورریختهشده نیز بسته میشوند، سیستم تضمین نمیکند که جلسههای خارج از محدوده چه زمانی بسته میشوند، بنابراین توصیه میکنیم که صریحاً روشهای close() را فراخوانی کنید.
ارسال پیام
برای ارسال پیام به دستگاهی دیگر، به موارد زیر نیاز دارید:
یک
DiscoverySession. این شیء به شما امکان میدهد باsendMessage()تماس بگیرید. برنامه شما با انتشار سرویس یا مشترک شدن در سرویس،DiscoverySessionدریافت میکند.PeerHandleدستگاه دیگر، برای مسیریابی پیام. برنامه شماPeerHandleدستگاه دیگری را به یکی از دو روش زیر دریافت میکند:- برنامه شما سرویسی را منتشر میکند و پیامی از مشترک دریافت میکند.
برنامه شما
PeerHandleمشترک را از فراخوانی برگشتیonMessageReceived()دریافت میکند. - برنامه شما در سرویسی مشترک میشود. سپس، وقتی ناشر منطبقی را پیدا میکند،
برنامه شما
PeerHandleناشر را از فراخوانی برگشتیonServiceDiscovered()دریافت میکند.
- برنامه شما سرویسی را منتشر میکند و پیامی از مشترک دریافت میکند.
برنامه شما
برای ارسال پیام، با
sendMessage() تماس بگیرید. سپس
ممکن است تماسهای برگشتی زیر رخ دهد:
- وقتی پیام با موفقیت توسط همتا دریافت شد، سیستم
onMessageSendSucceeded()فراخوانی برگشتی را در برنامه ارسالکننده فراخوانی میکند. - وقتی همتا پیامی دریافت میکند، سیستم
onMessageReceived()فراخوانی برگشتی را در برنامه دریافتکننده فراخوانی میکند.
اگرچه PeerHandle برای برقراری ارتباط با همتاها لازم است، نباید
به آن بهعنوان شناسه دائمی همتاها اتکا کنید. شناسههای سطح بالاتر را میتوان در برنامه کاربردی استفاده کرد--که در خود سرویس اکتشاف یا در پیامهای بعدی جاسازی شده است. میتوانید شناسهای را در سرویس اکتشاف با
روش
setMatchFilter()
یا
setServiceSpecificInfo()
PublishConfig یا
SubscribeConfig جاسازی کنید. روش
setMatchFilter() بر اکتشاف تأثیر میگذارد، درحالیکه روش
setServiceSpecificInfo() بر اکتشاف تأثیر نمیگذارد.
جاسازی شناسه در پیام بهمعنای اصلاح آرایه بایت پیام برای گنجاندن شناسه است (برای مثال، بهعنوان چند بایت اول).
ایجاد اتصال
Wi-Fi Aware از شبکهسازی مشتری-سرور بین دو دستگاه Wi-Fi Aware پشتیبانی میکند.
برای راهاندازی اتصال مشتری-سرور:
از «کشف Wi-Fi Aware» برای انتشار سرویس (در سرور) و مشترک شدن در سرویس (در کارخواه) استفاده کنید.
وقتی مشترک ناشر را پیدا کرد، پیامی از مشترک به ناشر ارسال کنید.
ServerSocketرا در دستگاه ناشر شروع کنید و درگاه آن را تنظیم یا دریافت کنید:کاتلین
val ss = ServerSocket(0) val port = ss.localPort
جاوا
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
از
ConnectivityManagerبرای درخواست شبکه Wi-Fi Aware در ناشر بااستفاده ازWifiAwareNetworkSpecifierاستفاده کنید، جلسه اکتشاف وPeerHandleمشترک را مشخص کنید، که از پیام ارسالشده توسط مشترک دریافت کردهاید:کاتلین
val networkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build() val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... } override fun onLost(network: Network) { ... } } connMgr.requestNetwork(myNetworkRequest, callback);
جاوا
NetworkSpecifier networkSpecifier = new WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build(); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... } @Override public void onLost(Network network) { ... } }; ConnectivityManager connMgr.requestNetwork(myNetworkRequest, callback);
وقتی ناشر درخواست شبکه میکند، باید پیامی به مشترک ارسال کند.
وقتی مشترک پیام را از ناشر دریافت کرد، بااستفاده از همان روشی که در ناشر استفاده شد، درخواست شبکه Wi-Fi Aware را در مشترک ارسال کنید. هنگام ایجاد
NetworkSpecifier، درگاهی را مشخص نکنید. وقتی اتصال شبکه دردسترس باشد، تغییر کند، یا قطع شود، روشهای فراخوانی مناسب فراخوانده میشوند.وقتی روش
onAvailable()در مشترک فراخوانی میشود، یک شیءNetworkدردسترس قرار میگیرد که با آن میتوانید یکSocketرا برای برقراری ارتباط باServerSocketدر ناشر باز کنید، اما باید نشانی IPv6 و درگاهServerSocketرا بدانید. اینها را از شیءNetworkCapabilitiesارائهشده در فراخوانی برگشتیonCapabilitiesChanged()دریافت میکنید:کاتلین
val peerAwareInfo = networkCapabilities.transportInfo as WifiAwareNetworkInfo val peerIpv6 = peerAwareInfo.peerIpv6Addr val peerPort = peerAwareInfo.port ... val socket = network.getSocketFactory().createSocket(peerIpv6, peerPort)
جاوا
WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo(); Inet6Address peerIpv6 = peerAwareInfo.getPeerIpv6Addr(); int peerPort = peerAwareInfo.getPort(); ... Socket socket = network.getSocketFactory().createSocket(peerIpv6, peerPort);
وقتی کارتان با اتصال شبکه تمام شد، با
مراجعه کنید.unregisterNetworkCallback()تماس بگیرید.
همتایان فاصلهسنجی و کاوش آگاه از مکان
دستگاهی با قابلیتهای مکان Wi-Fi RTT میتواند مستقیماً فاصله تا همتایان را اندازهگیری کند و از این اطلاعات برای محدود کردن کاوش سرویس Wi-Fi Aware استفاده کند.
Wi-Fi RTT API امکان محدوده مستقیم به همتای Wi-Fi Aware را بااستفاده از مک آدرس یا PeerHandle آن فراهم میکند.
میتوان کاوش Wi-Fi Aware را محدود کرد تا فقط سرویسهای درون یک حصار جغرافیایی خاص را کاوش کند. برای مثال، میتوانید حصار جغرافیاییای راهاندازی کنید که امکان کشف
دستگاهی را که سرویس "Aware_File_Share_Service_Name" منتشر میکند فراهم کند،
بهشرطی که فاصله آن کمتر از ۳ متر (بهصورت ۳٬۰۰۰ میلیمتر مشخص میشود) و بیشتر از ۱۰ متر
(بهصورت ۱۰٬۰۰۰ میلیمتر مشخص میشود) نباشد.
برای فعال کردن حصار جغرافیایی، هم ناشر و هم مشترک باید اقدام کنند:
ناشر باید بااستفاده از setRangingEnabled(true)، فاصلهیابی را در سرویس منتشرشده فعال کند.
اگر ناشر فاصلهیابی را فعال نکند، هرگونه محدودیت حصار جغرافیایی مشخصشده توسط مشترک نادیده گرفته میشود و کاوش عادی انجام میشود، و فاصله نادیده گرفته میشود.
مشترک باید بااستفاده از ترکیبی از setMinDistanceMm و setMaxDistanceMm یک حصار جغرافیایی مشخص کند.
برای هریک از این مقادیر، فاصله نامشخص بهمعنای عدم محدودیت است. فقط مشخص کردن حداکثر فاصله بهمعنای حداقل فاصله ۰ است. فقط مشخص کردن حداقل فاصله بهمعنای نبود حداکثر است.
وقتی سرویس همتایی در حصار جغرافیایی شناسایی میشود، onServiceDiscoveredWithinRange فراخوانی برگشتی راهاندازی میشود که فاصله اندازهگیریشده تا همتا را ارائه میدهد. سپس میتوان درصورت لزوم با Wi-Fi RTT API مستقیم تماس گرفت تا فاصله را در زمانهای بعدی اندازهگیری کرد.