অ্যান্ড্রয়েড ডিভাইসগুলির কি কোনও অনন্য আইডি রয়েছে এবং যদি তা হয় তবে জাভা ব্যবহার করে এটি অ্যাক্সেস করার সহজ উপায় কী?
অ্যান্ড্রয়েড ডিভাইসগুলির কি কোনও অনন্য আইডি রয়েছে এবং যদি তা হয় তবে জাভা ব্যবহার করে এটি অ্যাক্সেস করার সহজ উপায় কী?
উত্তর:
Settings.Secure#ANDROID_ID
প্রতিটি ব্যবহারকারীর 64-বিট হেক্স স্ট্রিংয়ের জন্য অ্যান্ড্রয়েড আইডিটিকে অনন্য হিসাবে ফিরিয়ে দেয় ।
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
আপডেট : অ্যান্ড্রয়েডের সাম্প্রতিক সংস্করণ হিসাবে, এর সাথে অনেকগুলি সমস্যা ANDROID_ID
সমাধান হয়েছে এবং আমি বিশ্বাস করি যে এই পদ্ধতির আর প্রয়োজন নেই। দয়া করে কটাক্ষপাত করা এন্থনি এর উত্তর ।
সম্পূর্ণ প্রকাশ: আমার অ্যাপটি নীচের পদ্ধতির মূলত ব্যবহার করেছে তবে এই পদ্ধতির আর ব্যবহার করে না এবং আমরা এখন অ্যান্ড্রয়েড বিকাশকারী ব্লগ এন্ট্রিতে বর্ণিত রূপটি ব্যবহার করি যা ইম্বির উত্তর লিঙ্কগুলিতে (যেমন, উত্পন্ন করা এবং সংরক্ষণ করা UUID#randomUUID()
))
এই প্রশ্নের অনেক উত্তর রয়েছে, যার বেশিরভাগই কেবল সময়ের "কিছু" কাজ করবে এবং দুর্ভাগ্যক্রমে এটি যথেষ্ট ভাল নয়।
আমার ডিভাইসগুলির পরীক্ষার উপর ভিত্তি করে (সমস্ত ফোন, যার মধ্যে কমপক্ষে একটি সক্রিয় করা হয়নি):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
প্রত্যাশিত (প্রত্যাশিত হিসাবে) এর জন্য বাতিলANDROID_ID
ANDROID_ID
এবং TelephonyManager.getDeviceId()
- যতক্ষণ না গুগল অ্যাকাউন্ট সেটআপের সময় যুক্ত করা হয়।সুতরাং আপনি যদি ডিভাইসে নিজেই কিছু অনন্য চান তবে যথেষ্ট TM.getDeviceId()
হওয়া উচিত । স্পষ্টতই কিছু ব্যবহারকারী অন্যের তুলনায় বেশি বেহায়া, সুতরাং এই 1 বা আরও শনাক্তকারীদের হ্যাশ করা কার্যকর হতে পারে, যাতে স্ট্রিংটি এখনও ডিভাইসের পক্ষে কার্যত অনন্য, তবে ব্যবহারকারীর আসল ডিভাইসটি স্পষ্টভাবে সনাক্ত করতে পারে না। উদাহরণস্বরূপ, String.hashCode()
ইউআইডির সাথে একত্রিত হয়ে:
final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
এর মতো কিছু হতে পারে: 00000000-54b3-e7c7-0000-000046bffd97
এটি আমার পক্ষে যথেষ্ট কাজ করে।
রিচার্ড নীচের হিসাবে উল্লেখ করেছেন, ভুলে যাবেন না যে আপনাকে TelephonyManager
সম্পত্তিগুলি পড়ার অনুমতি প্রয়োজন , সুতরাং এটি আপনার ম্যানিফেস্টে যুক্ত করুন:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
আমদানি libs
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
ম্যানিফেস্ট ফাইলটিতে যুক্ত মনে রাখবেন । যদি কোনও ডাটাবেসে সঞ্চয় করে থাকে, প্রত্যাবর্তিত স্ট্রিংটি 36 অক্ষর দীর্ঘ।
অনন্য আইডি, গুগল বিকাশকারী ব্লগ এবং অ্যান্ড্রয়েড ডকুমেন্টেশন তৈরির বিষয়ে প্রতিটি স্ট্যাক ওভারফ্লো পোস্ট পড়ার পরে আমি মনে করি যেন 'সিউডো আইডি' সেরা সম্ভাব্য বিকল্প।
স্যুয়েডো কোড:
if API >= 9/10: (99.5% of devices)
return unique ID containing serial id (rooted devices may be different)
else
return the unique ID of build information (may overlap data - API < 9)
আমাদের সমস্ত বিকল্প পোস্ট করার জন্য @ স্ট্যানসাল্টকে ধন্যবাদ (এই স্ট্যাক ওভারফ্লো প্রশ্নে)।
ব্যবহারকারী ইমেল - সফ্টওয়্যার
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
বা<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
( অ্যান্ড্রয়েড ডিভাইসের প্রাথমিক ইমেল ঠিকানা কীভাবে পাবেন )ব্যবহারকারী ফোন নম্বর - সফ্টওয়্যার
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
আইএমইআই - হার্ডওয়্যার (শুধুমাত্র ফোন, প্রয়োজন android.permission.READ_PHONE_STATE
)
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
অ্যান্ড্রয়েড আইডি - হার্ডওয়্যার (নালার হতে পারে, কারখানার পুনরায় সেট করার পরে পরিবর্তন করতে পারে, একটি মূলের ডিভাইসে পরিবর্তন করা যেতে পারে)
ডাব্লুএলএএন ম্যাক ঠিকানা - হার্ডওয়্যার (প্রয়োজন android.permission.ACCESS_WIFI_STATE
)
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
ব্লুটুথ ম্যাকের ঠিকানা - হার্ডওয়্যার (ব্লুটুথ সহ ডিভাইসগুলি android.permission.BLUETOOTH
)
<uses-permission android:name="android.permission.BLUETOOTH "/>
সিউডো-ইউনিক আইডি - সফ্টওয়্যার (সমস্ত অ্যান্ড্রয়েড ডিভাইসের জন্য)
আমি জানি অনুমতি ব্যবহার না করে অনন্য আইডি পাওয়ার কোনও 'নিখুঁত' উপায় নেই; তবে, কখনও কখনও আমাদের কেবল ডিভাইস ইনস্টলেশনটি ট্র্যাক করা দরকার। যখন কোনও অনন্য আইডি তৈরির কথা আসে, আমরা অতিরিক্ত অনুমতি ব্যবহার না করেই অ্যান্ড্রয়েড এপিআই আমাদের দেওয়া তথ্যের সম্পূর্ণ ভিত্তিতে একটি 'সিউডো ইউনিক আইডি' তৈরি করতে পারি। এইভাবে, আমরা ব্যবহারকারীর শ্রদ্ধা প্রদর্শন করতে এবং পাশাপাশি একটি ভাল ব্যবহারকারীর অভিজ্ঞতা দেওয়ার চেষ্টা করতে পারি।
সিউডো-ইউনিক আইডি দিয়ে, আপনি সত্যিকার অর্থেই চালিত হন যে অনুরূপ ডিভাইস রয়েছে এমন তথ্যের ভিত্তিতে নকল থাকতে পারে। আপনি সম্মিলিত পদ্ধতিটিকে আরও অনন্য করে তুলতে পারেন; তবে কিছু বিকাশকারীদের ডিভাইস ইনস্টলগুলি ট্র্যাক করা দরকার এবং এটি অনুরূপ ডিভাইসের উপর ভিত্তি করে কৌশল বা কার্য সম্পাদন করবে।
যদি তাদের অ্যান্ড্রয়েড ডিভাইসটি এপিআই 9 বা তার বেশি হয় তবে এটি 'বিল্ড.সিরিয়াল' ক্ষেত্রের কারণে অনন্য হওয়ার গ্যারান্টিযুক্ত।
মনে রাখবেন , আপনি প্রযুক্তিগতভাবে কেবল এপিআই <9 থাকা ব্যবহারকারীদের প্রায় 0.5% মিস করছেন । সুতরাং আপনি বিশ্রামের দিকে মনোনিবেশ করতে পারেন: এটি ব্যবহারকারীদের 99.5%!
যদি ব্যবহারকারীর অ্যান্ড্রয়েড ডিভাইস এপিআই 9 এর চেয়ে কম হয়; আশা করা যায়, তারা একটি ফ্যাক্টরি রিসেট করেনি এবং তাদের 'Secure.ANDROID_ID' সংরক্ষণ করা হবে বা 'নাল' নয়। ( http://developer.android.com/about/dashboards/index.html দেখুন )
যদি সমস্ত কিছু ব্যর্থ হয়, যদি ব্যবহারকারীর এপিআই 9 এর চেয়ে কম (জিঞ্জারব্রেডের চেয়ে কম) থাকে, তাদের ডিভাইসটি পুনরায় সেট করে ফেলেছে বা 'সিকিউর। এখানেই সংঘর্ষ ঘটতে পারে।
পরিবর্তন করুন:
নীচের পদ্ধতিটি একবার দেখুন:
/**
* Return pseudo unique ID
* @return ID
*/
public static String getUniquePsuedoID() {
// If all else fails, if the user does have lower than API 9 (lower
// than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
// returns 'null', then simply the ID returned will be solely based
// off their Android device information. This is where the collisions
// can happen.
// Thanks http://www.pocketmagic.net/?p=1662!
// Try not to use DISPLAY, HOST or ID - these items could change.
// If there are collisions, there will be overlapping data
String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// Thanks to @Roman SL!
// https://stackoverflow.com/a/4789483/950427
// Only devices with API >= 9 have android.os.Build.SERIAL
// http://developer.android.com/reference/android/os/Build.html#SERIAL
// If a user upgrades software or roots their device, there will be a duplicate entry
String serial = null;
try {
serial = android.os.Build.class.getField("SERIAL").get(null).toString();
// Go ahead and return the serial for api => 9
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
// String needs to be initialized
serial = "serial"; // some value
}
// Thanks @Joe!
// https://stackoverflow.com/a/2853253/950427
// Finally, combine the values we have found by using the UUID class to create a unique identifier
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
গুগল প্লে বিকাশকারীদের কনসোল থেকে:
আগস্ট 1 লা, 2014 থেকে শুরু করে, গুগল প্লে বিকাশকারী প্রোগ্রাম নীতিতে কোনও বিজ্ঞাপনের উদ্দেশ্যে অন্য ধ্রুবক শনাক্তকারীদের পরিবর্তে বিজ্ঞাপন আইডি ব্যবহার করার জন্য সমস্ত নতুন অ্যাপ আপলোড এবং আপডেটের প্রয়োজন requires আরও জানুন
বাস্তবায়ন :
অনুমতি:
<uses-permission android:name="android.permission.INTERNET" />
কোড:
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
import com.google.android.gms.common.GooglePlayServicesAvailabilityException;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import java.io.IOException;
...
// Do not call this function from the main thread. Otherwise,
// an IllegalStateException will be thrown.
public void getIdThread() {
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException exception) {
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesAvailabilityException exception) {
// Encountered a recoverable error connecting to Google Play services.
} catch (GooglePlayServicesNotAvailableException exception) {
// Google Play services is not available entirely.
}
final String id = adInfo.getId();
final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
}
উত্স / ডক্স:
http://developer.android.com/google/play-services/id.html http://developer.android.com/references/com/google/android/gms/ads/uthorfier/AdvertisingIdClient.html
গুগল প্লে পরিষেবাদি উপলব্ধ থাকাকালীন বিজ্ঞাপন আইডি অন্যান্য সনাক্তকারীদের বিদ্যমান ব্যবহারের (যেমন সেটিংসে ANDROID_ID ব্যবহারের ক্ষেত্রে.সিকিউর হিসাবে) সম্পূর্ণরূপে প্রতিস্থাপিত হয় intended গুগল প্লে পরিষেবাগুলি উপলভ্য নয় এমন কেসগুলি গুগলপ্লেসার্ভিসন নটঅভ্যালেবলএক্সেপশন getAdvertisingIdInfo () দ্বারা ছুঁড়ে ফেলা হচ্ছে by
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
আমি যে লিঙ্ক থেকে তথ্য নিয়েছি সেগুলি উল্লেখ করার চেষ্টা করেছি। আপনি অনুপস্থিত এবং অন্তর্ভুক্ত করা প্রয়োজন হলে, মন্তব্য করুন!
Build
ওএস আপডেটের ভিত্তিতে ক্লাস পরিবর্তন হবে না ? বিশেষত যদি এপিআই আপডেট হয়? যদি তাই হয় তবে কীভাবে আপনি গ্যারান্টি দিচ্ছেন যে এটি অনন্য? (আপনি যে পদ্ধতিটি লিখেছেন সে সম্পর্কে কথা বলছেন)
ডেভ ওয়েবে যেমন উল্লেখ করেছেন, অ্যান্ড্রয়েড বিকাশকারী ব্লগের একটি নিবন্ধ রয়েছে যা এটি কভার করে। তাদের পছন্দের সমাধানটি ডিভাইসের চেয়ে অ্যাপ্লিকেশন ইনস্টলগুলি ট্র্যাক করা এবং এটি বেশিরভাগ ব্যবহারের ক্ষেত্রে ভালভাবে কাজ করবে work ব্লগ পোস্টটি আপনাকে সেই কাজটি করার জন্য প্রয়োজনীয় কোডটি প্রদর্শন করবে এবং আমি আপনাকে এটি পরীক্ষা করে দেখার পরামর্শ দিচ্ছি।
তবে আপনার যদি অ্যাপ্লিকেশন ইনস্টলেশন শনাক্তকরণের পরিবর্তে কোনও ডিভাইস সনাক্তকারী প্রয়োজন হয় তবে ব্লগ পোস্ট সমাধানগুলি আলোচনা করতে চলেছে। আপনার প্রয়োজন এমন ইভেন্টে কয়েকটি আইটেমের অতিরিক্ত স্পষ্টতা পেতে আমি গুগলে কারও সাথে কথা বললাম। উপরে উল্লিখিত ব্লগ পোস্টে উল্লেখ করা হয়নি এমন ডিভাইস শনাক্তকারীদের সম্পর্কে আমি এখানে আবিষ্কার করেছি:
গুগলের সুপারিশগুলির ভিত্তিতে, আমি এমন একটি শ্রেণি প্রয়োগ করেছি যা প্রতিটি ডিভাইসের জন্য একটি অনন্য ইউআইডি উত্পন্ন করবে, যেখানে যথাযথভাবে টেলিফোনম্যানেজার.জেট ডেভিসআইডি () এ ফিরে আসা, এবং যথাযথভাবে বিকাশজনকভাবে উত্পন্ন অনন্য ইউআইডি-র অবলম্বন করে, বীজ হিসাবে ANDROID_ID ব্যবহার করে এটি অ্যাপ্লিকেশন পুনঃসূচনাগুলি জুড়ে রয়েছে (তবে অ্যাপ পুনরায় ইনস্টলেশনগুলি নয়)।
মনে রাখবেন যে ডিভাইসগুলির জন্য ডিভাইস আইডিতে ফ্যালব্যাক করতে হবে , অনন্য আইডি কারখানার পুনরায় সেট করা জুড়ে থাকবে। এটি সচেতন হওয়ার মতো বিষয়। আপনার যদি কোনও ফ্যাক্টরী রিসেটটি আপনার অনন্য আইডিটিকে পুনরায় সেট করবে তা নিশ্চিত করার প্রয়োজন হয় তবে আপনি ডিভাইস আইডির পরিবর্তে সরাসরি এলোমেলো ইউআইডি-তে ফিরে যাওয়ার বিষয়টি বিবেচনা করতে পারেন।
আবার, এই কোডটি কোনও ডিভাইস আইডির জন্য, কোনও অ্যাপ্লিকেশন ইনস্টলেশন আইডি নয়। বেশিরভাগ পরিস্থিতিতে, কোনও অ্যাপ্লিকেশন ইনস্টলেশন আইডি সম্ভবত আপনি যা খুঁজছেন তা। তবে আপনার যদি কোনও ডিভাইস আইডি দরকার হয় তবে নিম্নলিখিত কোডটি সম্ভবত আপনার জন্য কাজ করবে।
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
public class DeviceUuidFactory {
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
protected volatile static UUID uuid;
public DeviceUuidFactory(Context context) {
if (uuid == null) {
synchronized (DeviceUuidFactory.class) {
if (uuid == null) {
final SharedPreferences prefs = context
.getSharedPreferences(PREFS_FILE, 0);
final String id = prefs.getString(PREFS_DEVICE_ID, null);
if (id != null) {
// Use the ids previously computed and stored in the
// prefs file
uuid = UUID.fromString(id);
} else {
final String androidId = Secure.getString(
context.getContentResolver(), Secure.ANDROID_ID);
// Use the Android ID unless it's broken, in which case
// fallback on deviceId,
// unless it's not available, then fallback on a random
// number which we store to a prefs file
try {
if (!"9774d56d682e549c".equals(androidId)) {
uuid = UUID.nameUUIDFromBytes(androidId
.getBytes("utf8"));
} else {
final String deviceId = (
(TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE))
.getDeviceId();
uuid = deviceId != null ? UUID
.nameUUIDFromBytes(deviceId
.getBytes("utf8")) : UUID
.randomUUID();
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// Write the value out to the prefs file
prefs.edit()
.putString(PREFS_DEVICE_ID, uuid.toString())
.commit();
}
}
}
}
}
/**
* Returns a unique UUID for the current android device. As with all UUIDs,
* this unique ID is "very highly likely" to be unique across all Android
* devices. Much more so than ANDROID_ID is.
*
* The UUID is generated by using ANDROID_ID as the base key if appropriate,
* falling back on TelephonyManager.getDeviceID() if ANDROID_ID is known to
* be incorrect, and finally falling back on a random UUID that's persisted
* to SharedPreferences if getDeviceID() does not return a usable value.
*
* In some rare circumstances, this ID may change. In particular, if the
* device is factory reset a new device ID may be generated. In addition, if
* a user upgrades their phone from certain buggy implementations of Android
* 2.2 to a newer, non-buggy version of Android, the device ID may change.
* Or, if a user uninstalls your app on a device that has neither a proper
* Android ID nor a Device ID, this ID may change on reinstallation.
*
* Note that if the code falls back on using TelephonyManager.getDeviceId(),
* the resulting ID will NOT change after a factory reset. Something to be
* aware of.
*
* Works around a bug in Android 2.2 for many devices when using ANDROID_ID
* directly.
*
* @see http://code.google.com/p/android/issues/detail?id=10603
*
* @return a UUID that may be used to uniquely identify your device for most
* purposes.
*/
public UUID getDeviceUuid() {
return uuid;
}
}
এই বছরটি গুগল আই / ও উপস্থাপনায় ব্যবহারকারীর জন্য একটি অনন্য আইডি পেতে রেটো মেয়ার ব্যবহার করেছে:
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
public synchronized static String id(Context context) {
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
}
}
return uniqueID;
}
আপনি একটি ব্যাকআপ কৌশল মেঘ (এছাড়াও Reto এর বর্ণিত পছন্দগুলি পাঠাতে সঙ্গে দম্পতি এই যদি আলাপ , আপনি একটি আইডি থাকা উচিত যে একজন ব্যবহারকারী এবং প্রায় লাঠি বন্ধন ডিভাইস অপনোদিত পর হয়েছে, অথবা এমনকি প্রতিস্থাপন করা হয়। আমি এই ব্যবহারের পরিকল্পনা বিশ্লেষণে এগিয়ে যাওয়া (অন্য কথায়, আমি এখনও এটি কিছুটা করি নি :)।
এছাড়াও আপনি Wi-Fi অ্যাডাপ্টারের ম্যাক ঠিকানা বিবেচনা করতে পারেন। এইভাবে পুনরুদ্ধার করা:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
android.permission.ACCESS_WIFI_STATE
ম্যানিফেস্টে অনুমতি প্রয়োজন ।
Wi-Fi সংযুক্ত না থাকলেও উপলব্ধ থাকার জন্য প্রতিবেদন করা হয়েছে। যদি উপরের উত্তর থেকে জো যদি তার অনেকগুলি ডিভাইসে এটি ব্যবহার করে দেখায় তবে খুব ভাল লাগবে।
কিছু ডিভাইসে, Wi-Fi বন্ধ থাকা অবস্থায় এটি উপলব্ধ থাকে না।
দ্রষ্টব্য: অ্যান্ড্রয়েড 6.x থেকে, এটি ধারাবাহিক জাল ম্যাক ঠিকানা ফেরত দেয়:02:00:00:00:00:00
android.permission.ACCESS_WIFI_STATE
02:00:00:00:00:00
এখানে বরং দরকারী তথ্য আছে ।
এটি পাঁচটি পৃথক আইডি ধরণের:
android.permission.READ_PHONE_STATE
)android.permission.ACCESS_WIFI_STATE
)android.permission.BLUETOOTH
)অফিসিয়াল অ্যান্ড্রয়েড বিকাশকারী ব্লগের এখন ঠিক এই বিষয় সম্পর্কে একটি সম্পূর্ণ নিবন্ধ রয়েছে, অ্যাপ্লিকেশন ইনস্টলেশন সনাক্তকরণ ।
এ গুগল ইনপুট / আউটপুট Reto মায়ার এই যা ইনস্টলেশনের জুড়ে ব্যবহারকারীদের ট্র্যাক করতে সবচেয়ে ডেভেলপারদের চাহিদা পূরণ হবে কিভাবে কাছে একটি শক্তসমর্থ উত্তর মুক্তি। অ্যান্টনি নোলান তার উত্তরে দিকটি দেখায়, তবে আমি ভেবেছিলাম যে আমি সম্পূর্ণ পদ্ধতিটি লিখব যাতে অন্যেরা সহজেই এটি কীভাবে করতে পারে তা দেখতে (বিশদটি বের করতে আমার কিছুটা সময় লেগেছিল)।
এই পদ্ধতির সাহায্যে আপনাকে একটি বেনামে, সুরক্ষিত ব্যবহারকারী আইডি দেওয়া হবে যা ব্যবহারকারীর জন্য বিভিন্ন ডিভাইস জুড়ে (প্রাথমিক গুগল অ্যাকাউন্টের উপর ভিত্তি করে) এবং ইনস্টল জুড়ে স্থির থাকবে। প্রাথমিক পদ্ধতির র্যান্ডম ব্যবহারকারী আইডি উত্পন্ন করা এবং এটি অ্যাপ্লিকেশনগুলির ভাগ করা পছন্দগুলিতে সংরক্ষণ করা store তারপরে আপনি মেঘের সাথে গুগল অ্যাকাউন্টের সাথে লিঙ্কযুক্ত ভাগ করা পছন্দগুলি সংরক্ষণ করতে গুগলের ব্যাকআপ এজেন্ট ব্যবহার করেন।
পুরো পদ্ধতির মাধ্যমে চলুন। প্রথমত, আমাদের অ্যান্ড্রয়েড ব্যাকআপ পরিষেবাটি ব্যবহার করে আমাদের শেয়ারড প্রেফারেন্সগুলির জন্য একটি ব্যাকআপ তৈরি করতে হবে। এর মাধ্যমে আপনার অ্যাপ্লিকেশনটি নিবন্ধকরণ করে শুরু করুন http://developer.android.com/google/backup/signup.html
।
গুগল আপনাকে একটি ব্যাকআপ পরিষেবা কী দেবে যা আপনাকে ম্যানিফেস্টে যুক্ত করতে হবে। নীচে ব্যাকআপ এজেন্টটি ব্যবহার করতে আপনাকে অ্যাপ্লিকেশনটিও বলতে হবে:
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="your_backup_service_key" />
</application>
তারপরে আপনাকে ব্যাকআপ এজেন্ট তৈরি করতে হবে এবং ভাগ্য সংখ্যার জন্য সহায়ক এজেন্টটি ব্যবহার করতে বলুন:
public class MyBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "user_preferences";
// A key to uniquely identify the set of backup data
static final String PREFS_BACKUP_KEY = "prefs";
// Allocate a helper and add it to the backup agent
@Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
ব্যাকআপটি সম্পূর্ণ করতে আপনার মূল ক্রিয়াকলাপে আপনাকে ব্যাকআপ ম্যানেজারের একটি উদাহরণ তৈরি করতে হবে:
BackupManager backupManager = new BackupManager(context);
অবশেষে একটি ব্যবহারকারীর আইডি তৈরি করুন, যদি এটি ইতিমধ্যে বিদ্যমান না থাকে এবং এটিকে SharedPreferences এ সংরক্ষণ করুন:
public static String getUserID(Context context) {
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
MyBackupAgent.PREFS, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
//backup the changes
BackupManager mBackupManager = new BackupManager(context);
mBackupManager.dataChanged();
}
}
return uniqueID;
}
এই ব্যবহারকারী_আইডি এখন ইনস্টলেশনগুলি জুড়ে অবিচল থাকবে, এমনকি যদি ব্যবহারকারী ডিভাইসটি সরায়।
এই পদ্ধতির আরও তথ্যের জন্য রেটোর আলাপ দেখুন ।
এবং কীভাবে ব্যাকআপ এজেন্টটি প্রয়োগ করতে হয় তার সম্পূর্ণ বিশদের জন্য ডেটা ব্যাকআপ দেখুন । আমি বিশেষত টেস্টিংয়ের নীচের অংশটিকে সুপারিশ করি কারণ ব্যাকআপটি তাত্ক্ষণিকভাবে ঘটে না এবং তাই আপনাকে ব্যাকআপটি জোর করতে হবে তা পরীক্ষা করতে।
আমি মনে করি এটি অনন্য আইডির জন্য একটি কঙ্কাল তৈরির নিশ্চিত আগুনের উপায় ... এটি পরীক্ষা করে দেখুন।
সিউডো-ইউনিক আইডি, যা সমস্ত অ্যান্ড্রয়েড ডিভাইসে কাজ করে কিছু ডিভাইসে ফোন থাকে না (যেমন। ট্যাবলেটগুলি) বা কোনও কারণে, আপনি READ_PHONE_STATE অনুমতিটি অন্তর্ভুক্ত করতে চান না want আপনি এখনও রম সংস্করণ, প্রস্তুতকারকের নাম, সিপিইউ টাইপ এবং অন্যান্য হার্ডওয়্যারের বিবরণগুলির মতো বিশদটি পড়তে পারেন, আপনি যদি সিরিয়াল কী পরীক্ষার জন্য বা অন্য সাধারণ উদ্দেশ্যে আইডি ব্যবহার করতে চান তবে এটি উপযুক্ত। এইভাবে গণনা করা আইডিটি অনন্য হবে না: একই আইডি (একই হার্ডওয়্যার এবং রম চিত্রের উপর ভিত্তি করে) সহ দুটি ডিভাইস পাওয়া সম্ভব তবে বাস্তব-বিশ্বের অ্যাপ্লিকেশনগুলির পরিবর্তন নগণ্য। এই উদ্দেশ্যে আপনি বিল্ড ক্লাসটি ব্যবহার করতে পারেন:
String m_szDevIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
বিল্ড সদস্যদের বেশিরভাগ স্ট্রিং হয়, আমরা এখানে যা করছি তা হচ্ছে তাদের দৈর্ঘ্য নেওয়া এবং একটি ডিজিটের মাধ্যমে মডুলোর মাধ্যমে রূপান্তর করা। আমাদের এ জাতীয় ১৩ টি সংখ্যা রয়েছে এবং আমরা আইএমইআই (15 ডিজিট) এর মতো একই আকারের আইডি রাখতে সামনে (35) আরও দুটি যুক্ত করছি। এখানে অন্যান্য সম্ভাবনাগুলিও রয়েছে ভাল, কেবল এই স্ট্রিংগুলি একবার দেখুন। এর মতো কিছু ফেরত দেয় 355715565309247
। এই পদ্ধতির খুব সুবিধাজনক করে তোলে, কোন বিশেষ অনুমতি প্রয়োজন হয় না।
(অতিরিক্ত তথ্য: উপরে দেওয়া কৌশলটি পকেট যাদু সম্পর্কিত একটি নিবন্ধ থেকে অনুলিপি করা হয়েছিল ))
নিম্নলিখিত কোডটি একটি লুকানো অ্যান্ড্রয়েড API ব্যবহার করে ডিভাইস সিরিয়াল নম্বরটি দেয় returns তবে, এই কোডটি স্যামসং গ্যালাক্সি ট্যাবে কাজ করে না কারণ "ro.serialno" এই ডিভাইসে সেট করা নেই।
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
}
catch (Exception ignored) {
}
ro.serialno
উত্পন্ন করতে ব্যবহৃত হয় Settings.Secure.ANDROID_ID
। সুতরাং তারা মূলত একই মানের বিভিন্ন উপস্থাপনা।
ANDROID_ID
।
android.os.Build.SERIAL
android.os.Build.SERIAL
অ্যান্ড্রয়েড হে উঠিয়ে নেওয়া হবে দেখতে android-developers.googleblog.com/2017/04/...
এটি একটি সাধারণ প্রশ্ন, কোনও সহজ উত্তর নেই।
আরও বেশি, এখানে বিদ্যমান সমস্ত উত্তরই পুরানো বা অবিশ্বাস্য whether
সুতরাং আপনি যদি 2020 সালে কোনও সমাধান অনুসন্ধান করছেন ।
এখানে কিছু বিষয় মনে রাখা উচিত:
সমস্ত হার্ডওয়্যার ভিত্তিক শনাক্তকারী (এসএসএআইডি, আইএমইআই, ম্যাক, ইত্যাদি) অ-গুগলের ডিভাইসগুলির জন্য অবিশ্বাস্য (পিক্সেল এবং নেক্সাস ব্যতীত সমস্ত কিছুই), যা বিশ্বব্যাপী সক্রিয় ডিভাইসের 50% এর বেশি। সুতরাং সরকারী অ্যান্ড্রয়েড শনাক্তকারী সেরা অনুশীলনগুলি পরিষ্কারভাবে বলে:
হার্ডওয়্যার শনাক্তকারী যেমন এসএসএআইডি (অ্যান্ড্রয়েড আইডি), আইএমইআই, ম্যাক ঠিকানা ইত্যাদি ব্যবহার করা থেকে বিরত থাকুন ...
এটি উপরের উত্তরগুলির বেশিরভাগটিকে অবৈধ করে তোলে। এছাড়াও বিভিন্ন অ্যান্ড্রয়েড সুরক্ষা আপডেটের কারণে, তাদের মধ্যে কয়েকটিতে আরও নতুন এবং কঠোর রানটাইম অনুমতি দরকার হয়, যা ব্যবহারকারীরা কেবল অস্বীকার করতে পারেন।
উদাহরণ স্বরূপ CVE-2018-9489
যা উপরে উল্লিখিত সমস্ত ওয়াইফাই ভিত্তিক কৌশলকে প্রভাবিত করে।
এটি সেই শনাক্তকারীদের কেবল অবিশ্বাস্য নয়, অনেক ক্ষেত্রে অ্যাক্সেসযোগ্যও করে তোলে।
সুতরাং সহজ কথায়: এই কৌশলগুলি ব্যবহার করবেন না ।
এখানে আরও অনেক উত্তর এটি ব্যবহারের পরামর্শ দিচ্ছে AdvertisingIdClient
, এটিও বেমানান, কারণ এটির নকশা অনুসারে কেবল বিজ্ঞাপনের প্রোফাইলিংয়ের জন্য ব্যবহার করা উচিত। এটি সরকারী রেফারেন্সেও বলা হয়েছে
ব্যবহারকারীর প্রোফাইলিং বা বিজ্ঞাপন ব্যবহারের ক্ষেত্রে কেবল একটি বিজ্ঞাপন আইডি ব্যবহার করুন
এটি কেবল ডিভাইস সনাক্তকরণের জন্যই অবিশ্বাস্য নয়, তবে আপনাকে বিজ্ঞাপন ট্র্যাকিং সম্পর্কিত ব্যবহারকারীর গোপনীয়তাও অনুসরণ করতে হবে নীতি , যা স্পষ্টভাবে জানিয়েছে যে ব্যবহারকারী যে কোনও মুহূর্তে এটি পুনরায় সেট করতে বা অবরুদ্ধ করতে পারে।
সুতরাং এটি ব্যবহার করবেন না ।
যেহেতু আপনার পছন্দসই স্ট্যাটিক বিশ্বব্যাপী অনন্য এবং নির্ভরযোগ্য ডিভাইস সনাক্তকারী থাকতে পারে না। অ্যান্ড্রয়েডের অফিসিয়াল রেফারেন্সের পরামর্শ:
পেমেন্ট জালিয়াতি প্রতিরোধ এবং টেলিফোনি ব্যতীত অন্য সমস্ত ব্যবহারের ক্ষেত্রে ফায়ারবেসআইনস্ট্যান্সআইডি বা একটি ব্যক্তিগতভাবে সঞ্চিত জিইউডি ব্যবহার করুন।
এটি ডিভাইসে অ্যাপ্লিকেশন ইনস্টলেশনটির জন্য অনন্য, সুতরাং যখন ব্যবহারকারী অ্যাপটি আনইনস্টল করেন - এটি মুছে ফেলা হয়, সুতরাং এটি 100% নির্ভরযোগ্য নয়, তবে এটি পরবর্তী সেরা জিনিস।
আপনার গ্রেডে সর্বশেষতম ফায়ারবেস -বার্তাপ্রেরণ নির্ভরতাFirebaseInstanceId
যুক্ত করতে ব্যবহার করুন
implementation 'com.google.firebase:firebase-messaging:20.1.0'
এবং একটি পটভূমি থ্রেডে নীচের কোডটি ব্যবহার করুন:
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
আপনার যদি আপনার দূরবর্তী সার্ভারে ডিভাইস শনাক্তকরণ সংরক্ষণ করতে হয় তবে এটি (সরল পাঠ্য) মতো নয়, লবণযুক্ত একটি হ্যাশ সংরক্ষণ করুন ।
আজ এটি কেবল সেরা অনুশীলন নয়, আপনাকে অবশ্যই এটি জিডিপিআর অনুসারে আইন অনুসারে করতে হবে - শনাক্তকারী এবং অনুরূপ প্রবিধান।
নীচের কোডটি ব্যবহার করে, আপনি স্ট্রিং হিসাবে অ্যান্ড্রয়েড ওএস ডিভাইসের অনন্য ডিভাইস আইডি পেতে পারেন।
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
এপিআই স্তরের 9 (অ্যান্ড্রয়েড 2.3 - জিনজারড) এ শ্রেণিতে একটি সিরিয়াল ক্ষেত্র যুক্ত হয়েছিল Build
। ডকুমেন্টেশন বলছে এটি হার্ডওয়্যার ক্রমিক সংখ্যাটি উপস্থাপন করে। সুতরাং এটি অনন্য হওয়া উচিত, যদি এটি ডিভাইসে বিদ্যমান থাকে।
যদিও এপিআই স্তর> = 9 সহ সমস্ত ডিভাইস এটি (= নাল নয়) সমর্থিত কিনা তা আমি জানি না।
একটি জিনিস আমি যুক্ত করব - আমার সেই অনন্য পরিস্থিতিতে একটি আছে।
ব্যবহার:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
দেখা যাচ্ছে যে আমার ভিউজনিক জি ট্যাবলেট কোনও ডিভাইসআইডি প্রতিবেদন করে যা নাল নয়, প্রতিটি জি ট্যাবলেট একই সংখ্যার রিপোর্ট করে।
এটিকে "পকেট সাম্রাজ্য" খেলে আকর্ষণীয় করে তোলে যা আপনাকে "অনন্য" ডিভাইসআইডি ভিত্তিতে কারও অ্যাকাউন্টে তাত্ক্ষণিকভাবে অ্যাক্সেস দেয়।
আমার ডিভাইসে কোনও সেল রেডিও নেই।
9774d56d682e549c
?
আপনার অ্যাপ্লিকেশনটি ইনস্টল হওয়া প্রতিটি অ্যান্ড্রয়েড ডিভাইসের জন্য কীভাবে একটি অনন্য শনাক্তকারী পাবেন সে সম্পর্কে বিশদ নির্দেশাবলীর জন্য, অ্যাপ্লিকেশন ইনস্টলেশনগুলির সনাক্তকরণের জন্য সরকারী অ্যান্ড্রয়েড বিকাশকারী ব্লগ পোস্টিং দেখুন ।
মনে হচ্ছে আপনার পক্ষে ইনস্টলেশনের সময় নিজেকে তৈরি করা এবং অ্যাপ্লিকেশনটি পুনরায় চালু করার সময় এটি পড়ার সর্বোত্তম উপায়।
আমি ব্যক্তিগতভাবে এটি গ্রহণযোগ্য তবে আদর্শ নই। অ্যান্ড্রয়েড সরবরাহিত কোনও শনাক্তকারী সব ক্ষেত্রেই কাজ করে না কারণ বেশিরভাগ ফোনের রেডিও স্টেটস (ওয়াই-ফাই অন / অফ, সেলুলার অন / অফ, ব্লুটুথ অন / অফ) এর উপর নির্ভরশীল। অন্যগুলি Settings.Secure.ANDROID_ID
অবশ্যই নির্মাতার দ্বারা প্রয়োগ করা উচিত এবং অনন্য হওয়ার গ্যারান্টিযুক্ত নয়।
নীচে একটি ইনস্টলেশন ফাইলটিতে ডেটা লেখার একটি উদাহরণ যা অ্যাপ্লিকেশন স্থানীয়ভাবে সংরক্ষণ করা অন্য যে কোনও ডেটা সহ সংরক্ষণ করা হবে।
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
ক্লাস ফাইলে কোডের নীচে যুক্ত করুন:
final TelephonyManager tm = (TelephonyManager) getBaseContext()
.getSystemService(SplashActivity.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
Log.v("DeviceIMEI", "" + tmDevice);
tmSerial = "" + tm.getSimSerialNumber();
Log.v("GSM devices Serial Number[simcard] ", "" + tmSerial);
androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
Log.v("androidId CDMA devices", "" + androidId);
UUID deviceUuid = new UUID(androidId.hashCode(),
((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
Log.v("deviceIdUUID universally unique identifier", "" + deviceId);
String deviceModelName = android.os.Build.MODEL;
Log.v("Model Name", "" + deviceModelName);
String deviceUSER = android.os.Build.USER;
Log.v("Name USER", "" + deviceUSER);
String devicePRODUCT = android.os.Build.PRODUCT;
Log.v("PRODUCT", "" + devicePRODUCT);
String deviceHARDWARE = android.os.Build.HARDWARE;
Log.v("HARDWARE", "" + deviceHARDWARE);
String deviceBRAND = android.os.Build.BRAND;
Log.v("BRAND", "" + deviceBRAND);
String myVersion = android.os.Build.VERSION.RELEASE;
Log.v("VERSION.RELEASE", "" + myVersion);
int sdkVersion = android.os.Build.VERSION.SDK_INT;
Log.v("VERSION.SDK_INT", "" + sdkVersion);
AndroidManLive.xML এ যুক্ত করুন:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
TelephonyManager
এবং ANDROID_ID
, এর দ্বারা প্রাপ্ত:String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null) {
deviceId = mTelephony.getDeviceId();
}
else {
deviceId = Secure.getString(
getApplicationContext().getContentResolver(),
Secure.ANDROID_ID);
}
তবে আমি গুগলের পরামর্শ দেওয়া একটি পদ্ধতির দৃ strongly়তার সাথে সুপারিশ করছি, অ্যাপ্লিকেশন ইনস্টলেশন সনাক্তকরণ দেখুন ।
বিভিন্ন ANDROID_ID
বিষয়গুলি নিয়ে ( বিভিন্ন ক্ষেত্রে null
বা কোনও নির্দিষ্ট মডেলের ডিভাইস সর্বদা একই আইডি ফেরত আসতে পারে) কাজ করার জন্য বিভিন্ন বিষয়ে বিভিন্ন পদ্ধতি রয়েছে :
আমি নিজেই অ্যান্ড্রয়েডের জন্য একটি বিদ্যমান ওপেনউডিআইডি প্রয়োগকরণ ( https://github.com/ylechelle/OpenUDID দেখুন ) ব্যবহার করতে পছন্দ করি ( https://github.com/vieux/OpenUDID দেখুন )। এটি সংহত করা সহজ এবং ANDROID_ID
উপরে উল্লিখিত সমস্যাগুলির জন্য ফ্যালব্যাকগুলির সাথে ব্যবহার করে।
আইএমইআই সম্পর্কে কীভাবে । এটি অ্যান্ড্রয়েড বা অন্যান্য মোবাইল ডিভাইসের জন্য অনন্য।
এখানে আমি কীভাবে অনন্য আইডি তৈরি করছি:
public static String getDeviceId(Context ctx)
{
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice = tm.getDeviceId();
String androidId = Secure.getString(ctx.getContentResolver(), Secure.ANDROID_ID);
String serial = null;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL;
if(tmDevice != null) return "01" + tmDevice;
if(androidId != null) return "02" + androidId;
if(serial != null) return "03" + serial;
// other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)
return null;
}
আমার দুটি সেন্ট - এনবি এটি কোনও ডিভাইসের (ত্রুটিযুক্ত) স্বতন্ত্র আইডির জন্য - অ্যান্ড্রয়েড বিকাশকারীদের ব্লগে আলোচিত ইনস্টলেশন হিসাবে নয় ।
নোট করুন যে @ এমএমবি দ্বারা প্রদত্ত সমাধানটি প্রতিটি অ্যাপ্লিকেশন আইডিতে ফিরে আসে কারণ SharedPreferences পুরো প্রক্রিয়া জুড়ে সিঙ্ক্রোনাইজ হয় না (দেখুন এখানে এবং এখানে )। সুতরাং আমি একেবারে এড়ানো।
পরিবর্তে, আমি এনামে একটি ডিভাইস (আইডি) আইডি পাওয়ার জন্য বিভিন্ন কৌশল সজ্জিত করেছি - এনাম কনস্ট্যান্টগুলির ক্রম পরিবর্তন করা আইডি পাওয়ার বিভিন্ন পদ্ধতির অগ্রাধিকারকে প্রভাবিত করে। প্রথম নন-নাল আইডিটি ফেরত দেওয়া হয় বা একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয় (নালকে একটি অর্থ না দেওয়ার ভাল জাভা অভ্যাস অনুসারে)। সুতরাং উদাহরণস্বরূপ আমার কাছে প্রথমে টেলিফোন রয়েছে - তবে একটি ভাল ডিফল্ট পছন্দ হবে ANDROID_ID বিটা:
import android.Manifest.permission;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.util.Log;
// TODO : hash
public final class DeviceIdentifier {
private DeviceIdentifier() {}
/** @see http://code.google.com/p/android/issues/detail?id=10603 */
private static final String ANDROID_ID_BUG_MSG = "The device suffers from "
+ "the Android ID bug - its ID is the emulator ID : "
+ IDs.BUGGY_ANDROID_ID;
private static volatile String uuid; // volatile needed - see EJ item 71
// need lazy initialization to get a context
/**
* Returns a unique identifier for this device. The first (in the order the
* enums constants as defined in the IDs enum) non null identifier is
* returned or a DeviceIDException is thrown. A DeviceIDException is also
* thrown if ignoreBuggyAndroidID is false and the device has the Android ID
* bug
*
* @param ctx
* an Android constant (to retrieve system services)
* @param ignoreBuggyAndroidID
* if false, on a device with the android ID bug, the buggy
* android ID is not returned instead a DeviceIDException is
* thrown
* @return a *device* ID - null is never returned, instead a
* DeviceIDException is thrown
* @throws DeviceIDException
* if none of the enum methods manages to return a device ID
*/
public static String getDeviceIdentifier(Context ctx,
boolean ignoreBuggyAndroidID) throws DeviceIDException {
String result = uuid;
if (result == null) {
synchronized (DeviceIdentifier.class) {
result = uuid;
if (result == null) {
for (IDs id : IDs.values()) {
try {
result = uuid = id.getId(ctx);
} catch (DeviceIDNotUniqueException e) {
if (!ignoreBuggyAndroidID)
throw new DeviceIDException(e);
}
if (result != null) return result;
}
throw new DeviceIDException();
}
}
}
return result;
}
private static enum IDs {
TELEPHONY_ID {
@Override
String getId(Context ctx) {
// TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
final TelephonyManager tm = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
w("Telephony Manager not available");
return null;
}
assertPermission(ctx, permission.READ_PHONE_STATE);
return tm.getDeviceId();
}
},
ANDROID_ID {
@Override
String getId(Context ctx) throws DeviceIDException {
// no permission needed !
final String andoidId = Secure.getString(
ctx.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
if (BUGGY_ANDROID_ID.equals(andoidId)) {
e(ANDROID_ID_BUG_MSG);
throw new DeviceIDNotUniqueException();
}
return andoidId;
}
},
WIFI_MAC {
@Override
String getId(Context ctx) {
WifiManager wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (wm == null) {
w("Wifi Manager not available");
return null;
}
assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
// getMacAddress() has no java doc !!!
return wm.getConnectionInfo().getMacAddress();
}
},
BLUETOOTH_MAC {
@Override
String getId(Context ctx) {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
w("Bluetooth Adapter not available");
return null;
}
assertPermission(ctx, permission.BLUETOOTH);
return ba.getAddress();
}
}
// TODO PSEUDO_ID
// http://www.pocketmagic.net/2011/02/android-unique-device-id/
;
static final String BUGGY_ANDROID_ID = "9774d56d682e549c";
private final static String TAG = IDs.class.getSimpleName();
abstract String getId(Context ctx) throws DeviceIDException;
private static void w(String msg) {
Log.w(TAG, msg);
}
private static void e(String msg) {
Log.e(TAG, msg);
}
}
private static void assertPermission(Context ctx, String perm) {
final int checkPermission = ctx.getPackageManager().checkPermission(
perm, ctx.getPackageName());
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Permission " + perm + " is required");
}
}
// =========================================================================
// Exceptions
// =========================================================================
public static class DeviceIDException extends Exception {
private static final long serialVersionUID = -8083699995384519417L;
private static final String NO_ANDROID_ID = "Could not retrieve a "
+ "device ID";
public DeviceIDException(Throwable throwable) {
super(NO_ANDROID_ID, throwable);
}
public DeviceIDException(String detailMessage) {
super(detailMessage);
}
public DeviceIDException() {
super(NO_ANDROID_ID);
}
}
public static final class DeviceIDNotUniqueException extends
DeviceIDException {
private static final long serialVersionUID = -8940090896069484955L;
public DeviceIDNotUniqueException() {
super(ANDROID_ID_BUG_MSG);
}
}
}
এখানে 30+ উত্তর রয়েছে এবং কিছু একই এবং কিছু অনন্য। এই উত্তরটি সেই কয়েকটি উত্তরের ভিত্তিতে তৈরি। এর মধ্যে একটি হলেন @ লেন ডলিংয়ের উত্তর।
এটি 3 আইডি যুক্ত করে একটি 32-সংখ্যার হেক্স স্ট্রিং তৈরি করে। এটা আমার জন্য খুব ভাল কাজ করেছে।
3 টি আইডি হ'ল
সিউডো-আইডি - এটি শারীরিক ডিভাইসের স্পেসিফিকেশনগুলির ভিত্তিতে উত্পন্ন হয়
ANDROID_ID - Settings.Secure.ANDROID_ID
ব্লুটুথ ঠিকানা - ব্লুটুথ অ্যাডাপ্টারের ঠিকানা
এটি এর মতো কিছু ফিরে আসবে: 551F27C060712A72730B0A0F734064B1
দ্রষ্টব্য: আপনি longId
স্ট্রিংটিতে সর্বদা আরও আইডি যুক্ত করতে পারেন । উদাহরণস্বরূপ, সিরিয়াল #। ওয়াইফাই অ্যাডাপ্টারের ঠিকানা। আইএমইআই। এভাবে আপনি প্রতি ডিভাইসটিকে আরও অনন্য করে তুলছেন।
@SuppressWarnings("deprecation")
@SuppressLint("HardwareIds")
public static String generateDeviceIdentifier(Context context) {
String pseudoId = "35" +
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.HOST.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10;
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String btId = "";
if (bluetoothAdapter != null) {
btId = bluetoothAdapter.getAddress();
}
String longId = pseudoId + androidId + btId;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(longId.getBytes(), 0, longId.length());
// get md5 bytes
byte md5Bytes[] = messageDigest.digest();
// creating a hex string
String identifier = "";
for (byte md5Byte : md5Bytes) {
int b = (0xFF & md5Byte);
// if it is a single digit, make sure it have 0 in front (proper padding)
if (b <= 0xF) {
identifier += "0";
}
// add number to string
identifier += Integer.toHexString(b);
}
// hex string to uppercase
identifier = identifier.toUpperCase();
return identifier;
} catch (Exception e) {
Log.e("TAG", e.toString());
}
return "";
}
longId
: এটা সবচেয়ে অনন্য শনাক্তকারী করতে হবে এবং একটি ফাইল এ সঞ্চয়,String uuid = UUID.randomUUID().toString();
longId
। String longId = pseudoId + androidId + btId + UUID.randomUUID().toString();
এটির মতো একটি লাইন পরিবর্তন করুন: এটি গ্যারান্টি দেয় যে উত্পন্ন আইডিটি অনন্য হবে।
অন্য উপায়টি হ'ল /sys/class/android_usb/android0/iSerial
কোনও অ্যাপ্লিকেশনটিতে কোনও অনুমতি ছাড়াই ব্যবহার করা।
user@creep:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root root 4096 2013-01-10 21:08 iSerial
user@creep:~$ adb shell cat /sys/class/android_usb/android0/iSerial
0A3CXXXXXXXXXX5
জাভাতে এটি করার জন্য কেবলমাত্র একটি ফাইলআরপুট স্ট্রিম ব্যবহার করে আইশরিয়াল ফাইলটি খোলার জন্য এবং অক্ষরগুলি পড়তে হবে। কেবলমাত্র আপনি এটিকে একটি ব্যতিক্রম হ্যান্ডলারে মুড়িয়ে রাখুন তা নিশ্চিত করুন, কারণ সমস্ত ডিভাইসে এই ফাইলটি নেই।
কমপক্ষে নিম্নলিখিত ডিভাইসগুলির কাছে এই ফাইলটি বিশ্ব-পঠনযোগ্য হিসাবে পরিচিত:
আপনি আমার ব্লগ পোস্টটি অপ্রয়োজনীয় অ্যাপ্লিকেশনগুলিতে অ্যান্ড্রয়েড হার্ডওয়্যার সিরিয়াল নম্বর ফাঁস করতেও দেখতে পারেন যেখানে অন্যান্য ফাইলগুলি কী কী তথ্যের জন্য উপলভ্য তা নিয়ে আমি আলোচনা করি।
টেলিফোনম্যাঞ্জার.গেট ডেভিসআইডি () অনন্য ডিভাইস আইডি প্রদান করে, উদাহরণস্বরূপ, জিএসএমের জন্য আইএমইআই এবং সিডিএমএ ফোনগুলির জন্য এমইআইডি বা ইএসএন।
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
তবে আমি ব্যবহার করার পরামর্শ দিচ্ছি:
Settings.Secure.ANDROID_ID যে অনন্য 64 বিট হেক্স স্ট্রিং হিসেবে রিটার্ন অ্যান্ড্রয়েড আইডি।
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
কখনও কখনও টেলিফোনম্যাঙ্গার.গেট ডেভিসআইডি () নালাগুলি ফিরে আসবে, সুতরাং অনন্য আইডি নিশ্চিত করতে আপনি এই পদ্ধতিটি ব্যবহার করবেন:
public String getUniqueID(){
String myAndroidDeviceId = "";
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
}else{
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
}
return myAndroidDeviceId;
}
নির্দিষ্ট অ্যান্ড্রয়েড ডিভাইসের হার্ডওয়্যার স্বীকৃতির জন্য আপনি ম্যাক ঠিকানাগুলি পরীক্ষা করতে পারেন।
আপনি এটি যেভাবে করতে পারেন:
AndroidManLive.xML এ
<uses-permission android:name="android.permission.INTERNET" />
এখন আপনার কোডে:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
প্রতিটি অ্যান্ড্রয়েড ডিভাইসে তাদের কমপক্ষে একটি "wlan0" ইন্টারফেস ডাইনিটি ডাব্লুআই-এফআই চিপ হয়। WI-FI চালু না থাকা অবস্থায়ও এই কোডটি কাজ করে।
পিএস এগুলি হ'ল অন্যান্য ইন্টারফেসগুলির একটি গোছা যা আপনি ম্যাক্সের তালিকা থেকে পাবেন তবে এটি ফোনের মধ্যে পরিবর্তন হতে পারে।
IMEI
সিকিউরটি পেতে বা ব্যবহার করতে আমি নীচের কোডটি ব্যবহার করি । ANDROID_ID
বিকল্প হিসাবে, যখন ডিভাইসের ফোনের ক্ষমতা না থাকে:
String identifier = null;
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if (tm != null)
identifier = tm.getDeviceId();
if (identifier == null || identifier .length() == 0)
identifier = Secure.getString(activity.getContentResolver(),Secure.ANDROID_ID);
আরও নির্দিষ্টভাবে Settings.Secure.ANDROID_ID
,। এটি একটি -৪-বিট পরিমাণ যা উত্পাদিত এবং সংরক্ষণ করা হয় যখন ডিভাইসটি প্রথম বুট হয়। ডিভাইসটি মুছে ফেলা হলে এটি পুনরায় সেট করা হয়।
ANDROID_ID
একটি অনন্য ডিভাইস সনাক্তকারী জন্য একটি ভাল পছন্দ বলে মনে হচ্ছে। ডাউনসাইড রয়েছে: প্রথমত, এটি ২.২ এর আগে অ্যান্ড্রয়েড প্রকাশের ক্ষেত্রে ১০০% নির্ভরযোগ্য নয় এবং (“Froyo”).
এছাড়াও, কোনও বড় নির্মাতার কাছ থেকে জনপ্রিয় হ্যান্ডসেটে কমপক্ষে একটি বহুল পর্যবেক্ষণ করা বাগ পাওয়া গেছে, যেখানে প্রতিটি উদাহরণ একই অ্যান্ড্রয়েড_আইডি রয়েছে।
অ্যান্ড্রয়েড ডিভাইসে উপলভ্য ইউনিক আইডি বুঝতে understand এই অফিসিয়াল গাইড ব্যবহার করুন।
অনন্য শনাক্তকারীদের জন্য সেরা অনুশীলন:
ডিভাইসগুলি যাচাই করতে আইএমইআই, ম্যাক ঠিকানা, ইনস্ট্যান্স আইডি, জিইউইডি, এসএসএআইডি, বিজ্ঞাপন আইডি, সুরক্ষা নেট এপিআই।
https://developer.android.com/training/articles/user-data-ids
গুগল ইনস্ট্যান্স আইডি
I / O 2015 এ প্রকাশিত; অ্যান্ড্রয়েডে প্লে পরিষেবাগুলি 7.5 প্রয়োজন।
https://developers.google.com/instance-id/
https://developers.google.com/instance-id/guides/android-implementation
InstanceID iid = InstanceID.getInstance( context ); // Google docs are wrong - this requires context
String id = iid.getId(); // blocking call
দেখে মনে হচ্ছে গুগল এই আইডিটির জন্য অ্যান্ড্রয়েড, ক্রোম এবং আইওএস জুড়ে ইনস্টলেশন সনাক্ত করতে ব্যবহৃত হবে nds
এটি বরং একটি ডিভাইস একটি ইনস্টলেশন চিহ্নিত করে, কিন্তু তারপরে আবার, ANDROID_ID (যা স্বীকৃত উত্তর) এখন আর ডিভাইসগুলি সনাক্ত করে না। এআরসি রানটাইমের সাহায্যে প্রতিটি ইনস্টলসের (নতুন বিবরণ এখানে ) নতুন আইড্রোর আইডির মতো একটি নতুন অ্যান্ড্রয়েড_আইডি তৈরি করা হয় । এছাড়াও, আমি মনে করি ইনস্টলেশনগুলি সনাক্তকরণ (ডিভাইস নয়) আমাদের অধিকাংশই সন্ধান করছে।
উদাহরণ আইডির সুবিধা
এটি আমার কাছে উপস্থিত হয়েছে যে গুগল এ উদ্দেশ্যে (আপনার স্থাপনাগুলি সনাক্তকরণের জন্য) এটি ব্যবহার করার ইচ্ছা নিয়েছে, এটি ক্রস-প্ল্যাটফর্ম এবং অন্যান্য কয়েকটি উদ্দেশ্যে ব্যবহার করা যেতে পারে (উপরের লিঙ্কগুলি দেখুন)।
আপনি যদি সিসিএম ব্যবহার করেন, তবে আপনাকে শেষ পর্যন্ত এই ইনস্ট্যান্স আইডিটি ব্যবহার করতে হবে কারণ জিসিএম টোকেন পাওয়ার জন্য আপনার এটি প্রয়োজন (যা পুরানো জিসিএম রেজিস্ট্রেশন আইডি প্রতিস্থাপন করে)।
অসুবিধাগুলি / সমস্যাগুলি
বর্তমান প্রয়োগে (জিপিএস .5.৫) আপনার অ্যাপ্লিকেশন এটির অনুরোধ করলে সার্ভার থেকে দৃষ্টান্ত আইডিটি পুনরুদ্ধার করা হয়। এর অর্থ হ'ল উপরের কলটি একটি ব্লকিং কল - আমার অবৈজ্ঞানিক পরীক্ষায় ডিভাইসটি অনলাইনে থাকলে ১-২ সেকেন্ড এবং অফ-লাইনে ০.০ - ১.০ সেকেন্ড সময় লাগে (সম্ভবত এটি ছেড়ে দেওয়ার এবং তৈরি করার আগে এটি কতক্ষণ অপেক্ষা করে এলোমেলো আইডি)। উত্তর আমেরিকাতে অ্যান্ড্রয়েড 5.1.1 এবং জিপিএস 7.5 সহ নেক্সাস 5 এ এটি পরীক্ষা করা হয়েছিল।
আপনি যদি উদ্দেশ্যটির উদ্দেশ্যে আইডিটি ব্যবহার করেন - যেমন। অ্যাপ্লিকেশন প্রমাণীকরণ, অ্যাপ্লিকেশন শনাক্তকরণ, জিসিএম - আমি মনে করি এই 1-3 সেকেন্ডটি উপদ্রব হতে পারে (অবশ্যই আপনার অ্যাপের উপর নির্ভর করে)।
ANDROID_ID
পড়তে ভুলবেন না ।