diff --git a/README.rst b/README.rst index 6203c1b11..5a4dcec85 100644 --- a/README.rst +++ b/README.rst @@ -27,4 +27,5 @@ Notifications X X X X X Text to speech X X X X X Email (open mail client) X Vibrator X +Unique ID (IMEI or SN) X X X X X ================================== ============= ============= === ======= === ===== diff --git a/plyer/__init__.py b/plyer/__init__.py index 41ec578e2..43b6768db 100644 --- a/plyer/__init__.py +++ b/plyer/__init__.py @@ -4,7 +4,8 @@ ''' -__all__ = ('accelerometer', 'camera', 'gps', 'notification', 'tts', 'email', 'vibrator') +__all__ = ('accelerometer', 'camera', 'gps', 'notification', + 'tts', 'email', 'vibrator', 'uniqueid') __version__ = '1.1.2' from plyer import facades @@ -37,3 +38,7 @@ #: Vibrate proxy to :class:`plyer.facades.Vibrator` vibrator = Proxy( 'vibrator', facades.Vibrator) + +#: UniqueID proxy to :class:`plyer.facades.UniqueID` +uniqueid = Proxy( + 'uniqueid', facades.UniqueID) \ No newline at end of file diff --git a/plyer/facades.py b/plyer/facades.py index 2f5c10cd2..18c9c7420 100644 --- a/plyer/facades.py +++ b/plyer/facades.py @@ -261,3 +261,27 @@ def cancel(self): def _cancel(self, **kwargs): raise NotImplementedError() + +class UniqueID(object): + '''UniqueID facade. + + .. note:: + On Android your app needs the READ_PHONE_STATE permission and it returns IMEI. + Mac OSX > 10.5, it returns the serial number of the device, + Linux, it returns the serial number using lshw, and + Windows, it reads and returns MachineGUID from regkey. + ''' + + @property + def id(self): + '''Property that returns the unique id of the platform + ''' + return self.get_uid() + + def get_uid(self): + return self._get_uid() + + # private + + def _get_uid(self, **kwargs): + raise NotImplementedError() diff --git a/plyer/platforms/android/uniqueid.py b/plyer/platforms/android/uniqueid.py new file mode 100644 index 000000000..189f6490e --- /dev/null +++ b/plyer/platforms/android/uniqueid.py @@ -0,0 +1,16 @@ +from jnius import autoclass, cast +from plyer.platforms.android import activity +from plyer.facades import UniqueID + +TelephonyManager = autoclass('android.telephony.TelephonyManager') +Context = autoclass('android.content.Context') + +class AndroidUniqueID(UniqueID): + + def _get_uid(self): + manager = cast('android.telephony.TelephonyManager', + activity.getSystemService(Context.TELEPHONY_SERVICE)) + return manager.getDeviceId() + +def instance(): + return AndroidUniqueID() \ No newline at end of file diff --git a/plyer/platforms/linux/uniqueid.py b/plyer/platforms/linux/uniqueid.py new file mode 100644 index 000000000..79cb4c2b3 --- /dev/null +++ b/plyer/platforms/linux/uniqueid.py @@ -0,0 +1,18 @@ +from subprocess import Popen, PIPE +from plyer.facades import UniqueID + +class LinuxUniqueID(UniqueID): + def _get_uid(self): + lshw_process = Popen(["lshw", "-quiet"], stdout=PIPE, stderr=PIPE) + grep_process = Popen(["grep", "-m1" ,"serial:"], + stdin=lshw_process.stdout, stdout=PIPE) + lshw_process.stdout.close() + output = grep_process.communicate()[0] + + if output: + return output.split()[1] + else: + return None + +def instance(): + return LinuxUniqueID() \ No newline at end of file diff --git a/plyer/platforms/macosx/uniqueid.py b/plyer/platforms/macosx/uniqueid.py new file mode 100644 index 000000000..008eea8fa --- /dev/null +++ b/plyer/platforms/macosx/uniqueid.py @@ -0,0 +1,18 @@ +from subprocess import Popen, PIPE +from plyer.facades import UniqueID + +class OSXUniqueID(UniqueID): + def _get_uid(self): + ioreg_process = Popen(["ioreg", "-l"], stdout=PIPE) + grep_process = Popen(["grep", "IOPlatformSerialNumber"], + stdin=ioreg_process.stdout, stdout=PIPE) + ioreg_process.stdout.close() + output = grep_process.communicate()[0] + + if output: + return output.split()[3][1:-1] + else: + return None + +def instance(): + return OSXUniqueID() \ No newline at end of file diff --git a/plyer/platforms/win/uniqueid.py b/plyer/platforms/win/uniqueid.py new file mode 100644 index 000000000..ea52ad66e --- /dev/null +++ b/plyer/platforms/win/uniqueid.py @@ -0,0 +1,20 @@ +try: + import _winreg as regedit +except: + try: + import winreg as regedit + except: + raise NotImplemented() + +from plyer.facades import UniqueID + +class WinUniqueID(UniqueID): + + def _get_uid(self): + hKey = regedit.OpenKey(regedit.HKEY_LOCAL_MACHINE, + r"SOFTWARE\\Microsoft\\Cryptography") + value, _ = regedit.QueryValueEx (hKey, "MachineGuid") + return value + +def instance(): + return WinUniqueID() \ No newline at end of file