精华内容
下载资源
问答
  • imei 获取

    千次阅读 2017-07-13 15:40:45
    IMEI(International Mobile Equipment Identity)是国际移动设备身份码,在单卡工程中一个手机对应一个IMEI号,双卡工程中一张卡对应一个IMEI号。 下面是获得IMEI号的接口和demo code API: GSMP
    1)在Telephony Framework内部,可以直接使用GSMPhone或GeminiPhone提供的接口。
    KK之前的版本:
    IMEI(International Mobile Equipment Identity)是国际移动设备身份码,在单卡工程中一个手机对应一个IMEI号,双卡工程中一张卡对应一个IMEI号。
    下面是获得IMEI号的接口和demo code
    API:
    GSMPhone.java 中getDeviceId()
    GeminiPhone.java 中getDeviceId() 和 getDeviceIdGemini()

    Demo code:
    import com.android.internal.telephony.Phone;
    import com.android.internal.telephony.gemini.GeminiPhone;
    import com.android.internal.telephony.PhoneFactory; 
    Phone phone;
    phone = PhoneFactory.getDefaultPhone();
    String imei=(GeminiPhone)phone.getDeviceId();

    GeminiPhone mGeminiPhone;
    String imei_sim1 = mGeminiPhone.getDeviceIdGemini(PhoneConstants.GEMINI_SIM_1);
    String imei_sim2 = mGeminiPhone.getDeviceIdGemini(PhoneConstants.GEMINI_SIM_2);

    KK版本上:
    GSMPhone.java 中getDeviceId()
    GeminiPhone.java 其中getDeviceIdGemini()已经没有了,而getDeviceId()获取的是default phone的IMEI;
    所以直接使用GSMPhone.java中getDeviceId()方法; 
    Demo code:
    GeminiPhone mGeminiPhone;
    String imei_sim1=mGeminiPhone.getPhonebyId(PhoneConstants.GEMINI_SIM_1).getDeviceId();
    String imei_sim2=mGeminiPhone.getPhonebyId(PhoneConstants.GEMINI_SIM_2).getDeviceId();

    2)如需要在SDK开发(第三方APK)中获取IMEI号,请使用TelephonyManager中的getDeviceId()方法,或TelephonyManagerEx(双卡接口)中的getDeviceId(int simId)方法。
    Demo code(获取DefaultPhone的IMEI):
    import android.telephony.TelephonyManager;
    String imei_sim = TelephonyManager.getDeviceId();

    Demo code(双卡接口):
    import android.telephony.TelephonyManagerEx;
    String imei_sim1 = TelephonyManagerEx.getDeviceId(PhoneConstants.GEMINI_SIM_1);
    String imei_sim2 = TelephonyManagerEx.getDeviceId(PhoneConstants.GEMINI_SIM_2);
    展开全文
  • IMSI获取,IMEI获取

    2018-09-13 10:33:38
    IMSI获取 安卓手机IMSI 和IMEI获取,安装后打开即可看到
  • IOS IMEI 获取

    2015-09-24 15:48:23
    IOS IMEI 获取 // network.h // AUOiWay_Mobile // // Created by Mahmood1 on 2/21/12. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #import    #define SUPPORTS_...

    IOS IMEI 获取

    //  network.h

    //  AUOiWay_Mobile

    //

    //  Created by Mahmood1 on 2/21/12.

    //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.

    //

    #import <UIKit/UIKit.h>

     

    #define SUPPORTS_IOKIT_EXTENSIONS    1

     

    /*

     * To use, you must add the (semi)public IOKit framework before compiling

     */

     

    #if SUPPORTS_IOKIT_EXTENSIONS

    @interface UIDevice (IOKit_Extensions)

    - (NSString *) imei;

    - (NSString *) serialnumber;

    - (NSString *) backlightlevel;

    - (NSString *) macaddress;

    @end

    #endif

     

     

    //

    //  network.m

    //  AUOiWay_Mobile

    //

    //  Created by Mahmood1 on 2/21/12.

    //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.

    //

    #import "network.h"

    #include <sys/types.h>

    #include <sys/sysctl.h>

    #import <mach/mach_host.h>

    #include <netinet/in.h>

    #include <arpa/inet.h>

    #include <netdb.h>

    #include <ifaddrs.h>

    #include <sys/socket.h>

    #include <net/if.h>

    #include <net/if_dl.h>

    #include <ifaddrs.h>

     

    #if SUPPORTS_IOKIT_EXTENSIONS

    #pragma mark IOKit miniheaders

     

    #define kIODeviceTreePlane        "IODeviceTree"

     

    enum {

        kIORegistryIterateRecursively    = 0x00000001,

        kIORegistryIterateParents        = 0x00000002

    };

     

    typedef mach_port_t    io_object_t;

    typedef io_object_t    io_registry_entry_t;

    typedef char        io_name_t[128];

    typedef UInt32        IOOptionBits;

     

    CFTypeRef

    IORegistryEntrySearchCFProperty(

                                    io_registry_entry_t    entry,

                                    const io_name_t        plane,

                                    CFStringRef        key,

                                    CFAllocatorRef        allocator,

                                    IOOptionBits        options );

     

    kern_return_t

    IOMasterPort( mach_port_t    bootstrapPort,

                 mach_port_t *    masterPort );

     

    io_registry_entry_t

    IORegistryGetRootEntry(

                           mach_port_t    masterPort );

     

    CFTypeRef

    IORegistryEntrySearchCFProperty(

                                    io_registry_entry_t    entry,

                                    const io_name_t        plane,

                                    CFStringRef        key,

                                    CFAllocatorRef        allocator,

                                    IOOptionBits        options );

     

    kern_return_t   mach_port_deallocate

    (ipc_space_t                               task,

     mach_port_name_t                          name);

     

     

    @implementation UIDevice (IOKit_Extensions)

    #pragma mark IOKit Utils

    NSArray *getValue(NSString *iosearch)

    {

        mach_port_t          masterPort;

        CFTypeID             propID = (CFTypeID) NULL;

        unsigned int         bufSize;

     

        kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort);

        if (kr != noErr) return nil;

     

        io_registry_entry_t entry = IORegistryGetRootEntry(masterPort);

        if (entry == MACH_PORT_NULL) return nil;

     

        CFTypeRef prop = IORegistryEntrySearchCFProperty(entry,kIODeviceTreePlane, (CFStringRef) iosearch, nil,kIORegistryIterateRecursively);

        if (!prop) return nil;

     

        propID = CFGetTypeID(prop);

        if (!(propID == CFDataGetTypeID())) 

        {

            mach_port_deallocate(mach_task_self(), masterPort);

            return nil;

        }

     

        CFDataRef propData = (CFDataRef) prop;

        if (!propData) return nil;

     

        bufSize = CFDataGetLength(propData);

        if (!bufSize) return nil;

     

        //NSString *p1 = [[[NSString alloc] initWithBytes:CFDataGetBytePtr(propData) length:bufSize encoding:1] autorelease];

        NSString *p1 = [[[NSString alloc]initWithBytes:CFDataGetBytePtr(propData) length:bufSizeencoding:NSUTF8StringEncoding] autorelease];

        mach_port_deallocate(mach_task_self(), masterPort);

        return [p1 componentsSeparatedByString:@"/0"];

    }

     

    - (NSString *) imei

    {

        NSArray *results = getValue(@"device-imei");

        if (results)

        {

            //return [results objectAtIndex:0];

            NSString *string_content = [results objectAtIndex:0];

            const char *char_content = [string_content UTF8String];

            return  [[NSString alloc] initWithCString:(constchar*)char_content  encoding:NSUTF8StringEncoding];

     

        }

        //if(results)

        //{

        //    return [(NSString *)[results objectAtIndex:0] substringToIndex:2];

       // }

        return @"";

    }

     

    - (NSString *) serialnumber

    {

        NSArray *results = getValue(@"serial-number");

        if (results) return [results objectAtIndex:0];

        return nil;

    }

     

    - (NSString *) backlightlevel

    {

        NSArray *results = getValue(@"backlight-level");

        if (results) return [results objectAtIndex:0];

        return nil;

    }

     

    - (NSString *) macaddress

    {

        int                    mib[6];

        size_t                len;

        char                *buf;

        unsigned char        *ptr;

        struct if_msghdr    *ifm;

        struct sockaddr_dl    *sdl;

     

        mib[0] = CTL_NET;

        mib[1] = AF_ROUTE;

        mib[2] = 0;

        mib[3] = AF_LINK;

        mib[4] = NET_RT_IFLIST;

     

        if ((mib[5] = if_nametoindex("en0")) == 0) {

            printf("Error: if_nametoindex error/n");

            return NULL;

        }

     

        if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {

            printf("Error: sysctl, take 1/n");

            return NULL;

        }

     

        if ((buf = malloc(len)) == NULL) {

            printf("Could not allocate memory. error!/n");

            return NULL;

        }

     

        if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {

            printf("Error: sysctl, take 2");

            return NULL;

        }

     

        ifm = (struct if_msghdr *)buf;

        sdl = (struct sockaddr_dl *)(ifm + 1);

        ptr = (unsigned char *)LLADDR(sdl);

     

        NSString *outstring = [NSStringstringWithFormat:@"%02x%02x%02x%02x%02x%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];

        free(buf);

        return [outstring uppercaseString];

    }

     

     

     

    @end

    #endif

    展开全文
  • IMEI获取流程源码分析

    千次阅读 2018-11-24 14:56:24
    IMEI是设备唯一性的一个重要指标,这篇文章对IMEI获取做一些分析,以达到以下两个目的: 1、梳理Android源码中获取IMEI流程 2、理解获取IMEI时,源码中权限调用流程 备注:以下源码分析,针对的是Android 6.0.1...

    IMEI是设备唯一性的一个重要指标,这篇文章对IMEI获取做一些分析,以达到以下两个目的:

    1、梳理Android源码中获取IMEI流程

    2、理解获取IMEI时,源码中权限调用流程

    备注:以下源码分析,针对的是Android 6.0.1源码

     

    在Android代码中,我们需要获取设备的IMEI,只需调用下面方法

    
    TelephonyManager telephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    imei = telephonyMgr.getDeviceId();

    接下来就看看源码中是怎样获取IMEI的。

    
    /**
     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
     * or ESN for CDMA phones. Return null if device ID is not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     */
    public String getDeviceId() {
        try {
            ITelephony telephony = getITelephony();
            if (telephony == null)
                return null;
            return telephony.getDeviceId(mContext.getOpPackageName());
        } catch (RemoteException ex) {
            ......
        }
    }

    在TelephonyManager中,可以看到是先获取ITelephony对象,然后在通过该Interface的getDeviceid()方法来获取IMEI的。ITelephony是一个aidl的接口,所以接下来我们需要找到实现这个接口的对应实现类

    /**
     * Implementation of the ITelephony interface.
     */
    public class PhoneInterfaceManager extends ITelephony.Stub {
      
        ......
      
       /**
         * Returns the unique device ID of phone, for example, the IMEI for
         * GSM and the MEID for CDMA phones. Return null if device ID is not available.
         *
         * <p>Requires Permission:
         *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
         */
        @Override
        public String getDeviceId(String callingPackage) {
            if (!canReadPhoneState(callingPackage, "getDeviceId")) {
                return null;
            }
     
            final Phone phone = PhoneFactory.getPhone(0);
            if (phone != null) {
                return phone.getDeviceId();
            } else {
                return null;
            }
        }
      
        ......
    }

            首先,通过上面类的声明可以看到,PhoneInterfaceManager这个类实现了ITelephony.stub接口,因此就是这个接口的对应的实现类。接下来我们看看对应实现的getDeviceId()方法。

            这个方法首先通过canReadPhoneState()方法来判断权限是否通过,如果没有权限直接就返回null了。权限通过之后才会去获取deviceId。

            我们这次分析的目的,一个是权限流程分析,一个是IMEI获取流程分析,这里我们通过canReadPhoneState()方法看看权限相关的判断流程,然后在接着看IMEI的获取流程。

     

    1、权限判断流程

         通过上面canReadPhoneState()函数入口,我们看看具体的实现。

    private boolean canReadPhoneState(String callingPackage, String message) {
        try {
            mApp.enforceCallingOrSelfPermission(
                    android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
     
            // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
            return true;
        } catch (SecurityException e) {
            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
                    message);
        }
     
        if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return false;
        }
     
        return true;
    }

          该函数中,首先在try代码块中尝试获取READ_PRIVILEGED_PHONE_STATE权限,如果有这个权限就直接默认权限通过了。一般这个私有权限是系统的应用有,第三方应用都是没有的,所以会抛出安全异常,走到catch代码块中。

           在catch代码块,就是真正的去检查应用是否有对应需要的READ_PHONE_STATE权限了。接下来我们需要看看该方法的具体实现

    class ContextImpl extends Context {
        ......
      
        @Override
        public void enforceCallingOrSelfPermission(
                String permission, String message) {
            enforce(permission,
                    checkCallingOrSelfPermission(permission),
                    true,
                    Binder.getCallingUid(),
                    message);
        }
      
        @Override
        public int checkCallingOrSelfPermission(String permission) {
            if (permission == null) {
                throw new IllegalArgumentException("permission is null");
            }
     
            return checkPermission(permission, Binder.getCallingPid(),
                    Binder.getCallingUid());
        }
      
        @Override
        public int checkPermission(String permission, int pid, int uid) {
            if (permission == null) {
                throw new IllegalArgumentException("permission is null");
            }
     
            try {
                return ActivityManagerNative.getDefault().checkPermission(
                        permission, pid, uid);
            } catch (RemoteException e) {
                return PackageManager.PERMISSION_DENIED;
            }
        }
         
    }
      
    public abstract class ActivityManagerNative extends Binder implements IActivityManager {
        ......
      
        public int checkPermission(String permission, int pid, int uid)
                throws RemoteException {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            data.writeString(permission);
            data.writeInt(pid);
            data.writeInt(uid);
            mRemote.transact(CHECK_PERMISSION_TRANSACTION, data, reply, 0);
            reply.readException();
            int res = reply.readInt();
            data.recycle();
            reply.recycle();
            return res;
        }
      
        ......
    }

            从上面调用可以看到,首先是在ContextImpl中开始经过层层调用,在进程中最终调用到ActivityManagerNative中,通过Parcel传输相关数据,完成一次IPC操作来获取权限是否通过的结果。

            上述IPC操作,最终会调用到ActivityManagerService中完成,下面我们看看ActivityMangerService中的执行情况

    public final class ActivityManagerService extends ActivityManagerNative
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
        ......
      
        /**
         * As the only public entry point for permissions checking, this method
         * can enforce the semantic that requesting a check on a null global
         * permission is automatically denied.  (Internally a null permission
         * string is used when calling {@link #checkComponentPermission} in cases
         * when only uid-based security is needed.)
         *
         * This can be called with or without the global lock held.
         */
        @Override
        public int checkPermission(String permission, int pid, int uid) {
            if (permission == null) {
                return PackageManager.PERMISSION_DENIED;
            }
            return checkComponentPermission(permission, pid, uid, -1, true);
        }
      
        /**
         * This can be called with or without the global lock held.
         */
        int checkComponentPermission(String permission, int pid, int uid,
                int owningUid, boolean exported) {
            if (pid == MY_PID) {
                return PackageManager.PERMISSION_GRANTED;
            }
            return ActivityManager.checkComponentPermission(permission, uid,
                    owningUid, exported);
        }
         
    }
      
    public class ActivityManager {
        ......
      
        /** @hide */
        public static int checkComponentPermission(String permission, int uid,
                int owningUid, boolean exported) {
            // Root, system server get to do everything.
            final int appId = UserHandle.getAppId(uid);
            if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
                return PackageManager.PERMISSION_GRANTED;
            }
            // Isolated processes don't get any permissions.
            if (UserHandle.isIsolated(uid)) {
                return PackageManager.PERMISSION_DENIED;
            }
            // If there is a uid that owns whatever is being accessed, it has
            // blanket access to it regardless of the permissions it requires.
            if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
                return PackageManager.PERMISSION_GRANTED;
            }
            // If the target is not exported, then nobody else can get to it.
            if (!exported) {
                /*
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
                        here);
                */
                return PackageManager.PERMISSION_DENIED;
            }
            if (permission == null) {
                return PackageManager.PERMISSION_GRANTED;
            }
            try {
                return AppGlobals.getPackageManager()
                        .checkUidPermission(permission, uid);
            } catch (RemoteException e) {
                // Should never happen, but if it does... deny!
                Slog.e(TAG, "PackageManager is dead?!?", e);
            }
            return PackageManager.PERMISSION_DENIED;
        }
    }

    从上面调用可以看到,从ActivityManagerService的方法checkPermission()开始,最终会调用到ActivityManager的checkCompomentPermission()方法,最终完成权限的判断。

    从ActivityManager的checkCompomentPermission()方法中一堆的if语句,其实也不难发现,权限的判断,主要还是和appId,uid,pid等参数相关,一般第三方app都是通过PackageManagerService来判断的。

    下面是PMS中具体的判断逻辑,这里就不再进一步展开分析了,有兴趣的同学可以继续看看。

    public class PackageManagerService extends IPackageManager.Stub {  
        ......
      
        @Override
        public int checkUidPermission(String permName, int uid) {
            final int userId = UserHandle.getUserId(uid);
     
            if (!sUserManager.exists(userId)) {
                return PackageManager.PERMISSION_DENIED;
            }
     
            synchronized (mPackages) {
                Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
                if (obj != null) {
                    final SettingBase ps = (SettingBase) obj;
                    final PermissionsState permissionsState = ps.getPermissionsState();
                    if (permissionsState.hasPermission(permName, userId)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                    // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
                    if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
                            .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                } else {
                    ArraySet<String> perms = mSystemPermissions.get(uid);
                    if (perms != null) {
                        if (perms.contains(permName)) {
                            return PackageManager.PERMISSION_GRANTED;
                        }
                        if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && perms
                                .contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
                            return PackageManager.PERMISSION_GRANTED;
                        }
                    }
                }
            }
     
            return PackageManager.PERMISSION_DENIED;
        }
    }

     

    2、IMEI获取流程

          下面我们回到前面PhoneInterfaceManager中的getDeviceId()方法,继续分析获取IMEI的流程。

    /**
     * Implementation of the ITelephony interface.
     */
    public class PhoneInterfaceManager extends ITelephony.Stub {
      
        ......
      
       /**
         * Returns the unique device ID of phone, for example, the IMEI for
         * GSM and the MEID for CDMA phones. Return null if device ID is not available.
         *
         * <p>Requires Permission:
         *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
         */
        @Override
        public String getDeviceId(String callingPackage) {
            if (!canReadPhoneState(callingPackage, "getDeviceId")) {
                return null;
            }
     
            final Phone phone = PhoneFactory.getPhone(0);
            if (phone != null) {
                return phone.getDeviceId();
            } else {
                return null;
            }
        }
      
        ......
    

    从上面可以看到,首先是通过PhoneFactory拿到一个Phone对象,Phone是一个Interface,初步的实现类是PhoneBase。

    public abstract class PhoneBase extends Handler implements Phone {
      
    }

    看到对应类的声明,其实也是一个虚类,在这个类中也没有实现getDeviceId()方法,因此需要继续看看PhoneBase的实现类,发现有这么几个,分别是

    • CDMAPhone
    • GSMPhone
    • ImsPhoneBase
    • SipPhoneBase
    public class CDMAPhone extends PhoneBase {
        ......
      
        //returns MEID or ESN in CDMA
        @Override
        public String getDeviceId() {
            String id = getMeid();
            if ((id == null) || id.matches("^0*$")) {
                Rlog.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN");
                id = getEsn();
            }
            return id;
        }
    }
      
    public class GSMPhone extends PhoneBase {
        ......
      
        @Override
        public String getDeviceId() {
            return mImei;
        }
    }
      
    abstract class ImsPhoneBase extends PhoneBase {
        ......
      
        @Override
        public String getDeviceId() {
            return null;
        }
    }
      
    abstract class SipPhoneBase extends PhoneBase {
        ......
      
        @Override
        public String getDeviceId() {
            return null;
        }
      
    }

    可以看出,GSMPhone应该是提供IMEI的类。下面我们具体看看在GSMPhone中,mImei这个全局变量是怎样赋值的。

    
    public class GSMPhone extends PhoneBase {
        ......
      
        @Override
        public void handleMessage (Message msg) {
             ......
             switch (msg.what) {
                case EVENT_RADIO_AVAILABLE: {
                    mCi.getBasebandVersion(
                            obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
     
                    mCi.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
                    mCi.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE));
                    mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
                    startLceAfterRadioIsAvailable();
                }
                break;
                ......
      
                case EVENT_GET_IMEI_DONE:
                    ar = (AsyncResult)msg.obj;
     
                    if (ar.exception != null) {
                        break;
                    }
     
                    mImei = (String)ar.result;
                break;
                ......
        }
    }

    通过上面代码可以看到,在handleMessage()方法中,收到EVENT_GET_IMEI_DONE消息后,就得到了IMEI。进一步发现,上面有一行代码

                 mCi.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
    发送了这个消息出去,于是我们继续看看前面的调用mCi是什么。

           mCi是GSMPhone基类PhoneBase中的一个全局变量,其类型为CommandsInterface,为一个Interface,接下来就看看这个Interface的实现,这里就举出所有实现类型了,实现这个Interface的是RIL这个类

    
    public final class RIL extends BaseCommands implements CommandsInterface {
        ......
      
        @Override
        public void
        getIMEI(Message result) {
            RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);
     
            if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
     
            send(rr);
        }
      
        private void
        send(RILRequest rr) {
            Message msg;
     
            if (mSocket == null) {
                rr.onError(RADIO_NOT_AVAILABLE, null);
                rr.release();
                return;
            }
     
            msg = mSender.obtainMessage(EVENT_SEND, rr);
     
            acquireWakeLock();
     
            msg.sendToTarget();
        }
    }

    看到上面代码,在RIL类中,将获取IMEI的消息进行一些包装,然后在send()方法中通过mSender对象发送出去了。mSender是什么了?其实也在RIL这个类中,是个内部类,叫RILSender

    class RILSender extends Handler implements Runnable {
        ......
      
        @Override public void
        handleMessage(Message msg) {
             ......
             switch (msg.what) {
                    case EVENT_SEND:
                        try {
                            LocalSocket s;
     
                            s = mSocket;
     
                            if (s == null) {
                                rr.onError(RADIO_NOT_AVAILABLE, null);
                                rr.release();
                                decrementWakeLock();
                                return;
                            }
     
                            synchronized (mRequestList) {
                                mRequestList.append(rr.mSerial, rr);
                            }
     
                            byte[] data;
     
                            data = rr.mParcel.marshall();
                            rr.mParcel.recycle();
                            rr.mParcel = null;
     
                            if (data.length > RIL_MAX_COMMAND_BYTES) {
                                throw new RuntimeException(
                                        "Parcel larger than max bytes allowed! "
                                                              + data.length);
                            }
     
                            // parcel length in big endian
                            dataLength[0] = dataLength[1] = 0;
                            dataLength[2] = (byte)((data.length >> 8) & 0xff);
                            dataLength[3] = (byte)((data.length) & 0xff);
     
                            //Rlog.v(RILJ_LOG_TAG, "writing packet: " + data.length + " bytes");
     
                            s.getOutputStream().write(dataLength);
                            s.getOutputStream().write(data);
                        } catch {
                            ......
                        }
        }
    }

    熟悉电话框架这块的同学应该比较了解,电话这块,其实也是一个RILSender和一个RILReceiver,分别用于发送和接收。两个分别运行在不同线程,全双工工通信,处理RILRequest和RILResponse。

    这里不展开讲Android的电话框架,直接进入处理部分,看看上面发送的消息,是怎样被处理的。

    /**
     * Call from RIL to us to make a RIL_REQUEST
     *
     * Must be completed with a call to RIL_onRequestComplete()
     *
     * RIL_onRequestComplete() may be called from any thread, before or after
     * this function returns.
     *
     * Will always be called from the same thread, so returning here implies
     * that the radio is ready to process another command (whether or not
     * the previous command has completed).
     */
    static void
    onRequest (int request, void *data, size_t datalen, RIL_Token t) {
        ......
      
        case RIL_REQUEST_GET_IMEI:
            p_response = NULL;
            err = at_send_command_numeric("AT+CGSN", &p_response);
     
            if (err < 0 || p_response->success == 0) {
                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
            } else {
                RIL_onRequestComplete(t, RIL_E_SUCCESS,
                    p_response->p_intermediates->line, sizeof(char *));
            }
            at_response_free(p_response);
            break;
      
       ......
      
    }
    -------------------------------------------------------------------------------
    int at_send_command_numeric (const char *command,
                                     ATResponse **pp_outResponse)
    {
        int err;
        err = at_send_command_full (command, NUMERIC, NULL,
                                        NULL, 0, pp_outResponse);
        ......
        return err;
    }
    -------------------------------------------------------------------------------
    static int at_send_command_full (const char *command, ATCommandType type,
                        const char *responsePrefix, const char *smspdu,
                        long long timeoutMsec, ATResponse **pp_outResponse)
    {
        int err;
        ......
        err = at_send_command_full_nolock(command, type,
                        responsePrefix, smspdu,
                        timeoutMsec, pp_outResponse);
     
        ......
        return err;
    }
    -------------------------------------------------------------------------------
    /**
     * Internal send_command implementation
     * Doesn't lock or call the timeout callback
     *
     * timeoutMsec == 0 means infinite timeout
     */
     
    static int at_send_command_full_nolock (const char *command, ATCommandType type,
                        const char *responsePrefix, const char *smspdu,
                        long long timeoutMsec, ATResponse **pp_outResponse)
    {
        int err = 0;
        ......
     
        err = writeline (command);
     
        s_type = type;
        s_responsePrefix = responsePrefix;
        s_smsPDU = smspdu;
        sp_response = at_response_new();
     
        while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
            if (timeoutMsec != 0) {
                ......
            } else {
                err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
            }
            ......
        }
     
        ......
        err = 0;
    error:
        clearPendingCommand();
        return err;
    }

    上面代码比较多,主要是与硬件层打交道,将获取IMEI的命令写到硬件层,然后等待结果。这样子,通过写命令到硬件层,然后等待对应的IMEI数据被写到对应申请的内存地址后,就可以返回了。

    接着底层通过相应的IPC通道将数据返回给调用进程,调用进程读取对应的数据,就拿到了IMEI了。

    展开全文
  • Android 获取CellId以及IMEI 获取基站id

    千次阅读 2017-09-16 13:41:40
    //String imei = tm.getDeviceId(); } else { tv_cid.setText("cell identity:基站未连接"); } } 权限 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">...


    private void setCellIdentity() {
            if (isMobileConnected(this)) {
                System.out.println("基站已连接");
                int cellid=0;
                TelephonyManager tel = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
                CellLocation cel = tel.getCellLocation();
                //移动联通 GsmCellLocation
                if (cel instanceof GsmCellLocation) {
                    GsmCellLocation gsmCellLocation = (GsmCellLocation) cel;
                    cellid = gsmCellLocation.getCid();
                }else if(cel instanceof CdmaCellLocation){
                    //电信   CdmaCellLocation
                    CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) cel;
                    cellid = cdmaCellLocation.getBaseStationId();
                }
    
                tv_cid.setText("cell identity:" + cellid);
                //String imei = tm.getDeviceId();
            } else {
                tv_cid.setText("cell identity:基站未连接");
            }
        }




    权限

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    < uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>

    展开全文
  • [[NSUserDefaults standardUserDefaults] valueForKey:@"SBFormattedPhoneNumber...获取手机的IMEI #import "Message/NetworkController.h"  NetworkController *ntc=[[NetworkController sharedInstance] autorelea
  • 发现无系统权限的应用无法获取到可作为唯一标识的IMEI,MAC等等;由于我们的项目自己做了数据采集,项目中也接入了百度、头条、腾讯的广告等都需要获取设备唯一标识作为数据分析和收益统计的依据。于是适应行业,...
  • 获取本地iphone手机号码 [[NSUserDefaults standardUserDefaults] valueForKey:@...获取手机号码,和IMEI  NetworkController *ntc=[[NetworkController sharedInstance] autorelease]; NSStr
  • 1、使用手机主板+系统定制商+... * Pseudo-Unique ID, 这个在任何Android手机中都有效 解决手机中IMEI获取不到情况,兼容所有手机 */ public static String getIMEINew(Context context) { //we make this look li...
  • 引言在app开发中接口经常需要客户端传一个唯一的设备ID,用于校验设备重复登录问题等等,我们常常是传Android手机的deviceid,也就是手机的IMEI码,IMEI只有...获取手机的IMEI方案TelephonyManager TelephonyM...
  • 如何获取imei 和meid

    2020-07-21 09:51:11
    IMEI获取 private TelephonyManager telMgr; telMgr = TelephonyManager.from(mContext); imei_0 = telMgr.getImei(1); MEID获取 public String GetPhoneInfo(int slotId) { TelephonyManager telephonyManager = ...
  • Android 获取IMEI(Android 10以下可用)

    万次阅读 2019-07-09 17:49:47
    1、获取手机IMEI,从android 5.0之后通过getImei获取 public static String getIMEI(Context context){ String imei = ""; try { TelephonyManager tm = (TelephonyManager) context.getSystemService...
  • 获取IMEI号码

    2013-06-27 11:26:01
    获取IMEI号码
  • ios获取imei

    热门讨论 2013-11-20 10:34:22
    ios 获取imei代码,需要添加iokit框架
  • android 获取Imei

    千次阅读 2017-10-24 15:00:27
    android 获取手机的标识符imei
  • 获取imei

    2011-12-24 19:22:42
    网上看到的说法,还没有用过,先在这里收藏一下,留作日后使用。 #import "Message/NetworkController.h"NetworkController *ntc=[[NetworkController ...NSString *imeistring = [ntc IMEI];...
  • android获取IMEI

    2012-11-05 13:15:42
    android获取IMEI
  • 获取手机IMEI

    千次阅读 2019-07-26 08:35:55
    /** * 获取手机IMEI * * @param context * @return */ public static final String getDeviceId(Context context) { try { TelephonyManager telephonyManager = (Tel...
  • 不同手机设备 获取IMEI不同手机设备 获取IMEI不同手机设备 获取IMEI不同手机设备 获取IMEI不同手机设备 获取IMEI
  • 一、iOS7以后不能获取手机IMEI iOS 2.0版本以后UIDevice提供一个获取设备唯一标识符的方法uniqueIdentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符。好景不长,因为该...
  • 获取IMEI

    2010-08-13 14:08:53
    在J2ME中获取手机IMEI时,不同机型返回的串格式会有不同,有些会带有空格符号,当URL要带上IMEI时,必须把空格去掉, 以下是获取IMEI的方法:当获取IMEI为NULL时,尝试各厂商不同的方法去获取IMEI [code="...
  • C# 获取IMEI获取移动设备手机串号手机编码号源代码
  • 手机IMEI串码获取

    千次阅读 2017-02-09 14:41:45
    获取IMEI串码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,435
精华内容 574
关键字:

imei获取