精华内容
下载资源
问答
  • 2021-02-05 21:18:33

    文章首发微信公众号:QDROID88888,如果感兴趣可以关注一下公众号。

    一、测试gps定位功能的方法探讨

    在安卓App gps定位开发过程中,往往需要进行GPS定位的测试。由于室内gps信号被挡住了,所以如果需要测试gps定位的代码,要么跑到室外去等待gps定位更新或者使用安卓sdk中提供的"MOCK_LOCATION"功能编写额外的测试代码来模拟gps位置更新。如果从系统定制的角度出发,也可以根据gps上报的流程来模拟gps上报的逻辑实现模拟gps 的定位数据。

    二、修改系统实现模拟gps数据上报

    2.1 安卓系统上报gps数据流程总结

    在之前的文章安卓10源码开发定制(21)GPS定位研究(2)gps位置改变监听源码分析中已经分析安卓系统中gps数据上报的大概流程:

    1. 当gps位置改变更新,com_android_server_location_GnssLocationProvider.cpp中通过反射调用GnssLocationProvider.java中的reportLocation方法将gps数据上报到安卓系统java层。

    2. GnssLocationProvider.java中使用LocationProvider.java提供的onReportLocation方法将gps数据上报到GPS 位置管理器。

    3

    更多相关内容
  • android 地理位置信息修改 Android中修改地理位置信息
  •  现在很多的应用都是基于位置服务的,而且把位置服务作为重要的参考标准,其实这是很不安全的,位置信息的...这一期我们来探讨一下如何修改手机中的定位信息。太基础的原理我就不多说了,可以参考前几期文章。  ...

    https://blog.csdn.net/aggresss/article/details/54323034

            现在很多的应用都是基于位置服务的,而且把位置服务作为重要的参考标准,其实这是很不安全的,位置信息的数据未经过任何加密,而且是从我们的手机中发送出去的,所以是可以修改的。这一期我们来探讨一下如何修改手机中的定位信息。太基础的原理我就不多说了,可以参考前几期文章。
            先整理一下思路,Android在开发者模式下有一个"允许模拟位置选项",它是location service加载 MOCK location provider 实现的,通过这种线程注入的方式修改GPS信息是hacker们最喜欢的方式,但现在很多应用已经可以检测到这种注入方式而被屏蔽掉,也就是说如果我们只在APP层面上想解决方法总是有被检测出来的可能。那我们就得把问题往深了想,通过修改最底层的GPS数据来欺骗APP,在Framework层面上没有任何修改迹象,这样基于APP层面的检测机制就拿我们没有任何办法。
            思路确定后我们来探讨实践路线,首先我们要建立一个管道,让我们想要定位的GPS数据提交到Android操作系统的最底层,也就是Linux Kernel层面;然后我们要修改 GPS的 location report 机制,让它从内核中提取到我们的数据,然后逐层上报到APP层。有点明修栈道暗度陈仓的感觉。
            总体来说分成两部实现:1.建立到系统内核的数据管道;2.修改GPS上报机制。
            这次实验使用的是闲置的小米3W手机,编译源码采用CyanogenMod-13,具体的编译环境搭建和编译方法请参考前几期文章。
            因为Android系统从内核态到APP层要经过很多的层次,所以对于建立数据管道的步骤比较繁琐,我这里分成了5个步骤,对应5个层面来实现,每一步分别对应Android的 Kernel driver,HAL,JNI,Framework,Application。所有的代码我都已上传github中https://github.com/aggresss/PHDemo/  这一期的代码在VirtualPosition 目录下。
    下面描述一下实践步骤:
    =============分割线1==============
    第一步,修改Kernel driver
    进入 kernel/xiaomi/cancro/drivers 目录下,新建vp.h文件

    #ifndef _VP_ANDROID_H_  
    #define _VP_ANDROID_H_  
      
    #include <linux/cdev.h>  
    #include <linux/semaphore.h>  
      
    #define VP_DEVICE_NODE_NAME  "vp"  
    #define VP_DEVICE_FILE_NAME  "vp"  
    #define VP_DEVICE_PROC_NAME  "vp"  
    #define VP_DEVICE_CLASS_NAME "vp"  
      
    typedef struct {
        int toggle;
        double virtual_latitude;
        double virtual_longitude;
    } VirtualPosition;
     
     
     
     
    struct vp_android_dev {  
        int lamp;
        VirtualPosition val;
        struct semaphore sem;  
        struct cdev dev;  
    };    
    #endif  


    新建vp.c文件

    /*******************************************
    *include file and define functions
    *******************************************/
    #include <linux/init.h>  
    #include <linux/module.h>  
    #include <linux/types.h>  
    #include <linux/fs.h>  
    #include <linux/proc_fs.h>  
    #include <linux/device.h>  
    #include <asm/uaccess.h>  
      
    #include "vp.h"  
      
    /*主设备和从设备号变量*/  
    static int vp_major = 0;  
    static int vp_minor = 0;  
      
    /*设备类别和设备变量*/  
    static struct class* vp_class = NULL;  
    static struct vp_android_dev* vp_dev = NULL;  
      
    /*传统的设备文件操作方法*/  
    static int vp_open(struct inode* inode, struct file* filp);  
    static int vp_release(struct inode* inode, struct file* filp);  
    static ssize_t vp_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);  
    static ssize_t vp_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);  
      
    /*设备文件操作方法表*/  
    static struct file_operations vp_fops = {  
        .owner = THIS_MODULE,  
        .open = vp_open,  
        .release = vp_release,  
        .read = vp_read,  
        .write = vp_write,   
    };  
      
    /*访问设置属性方法*/  
    static ssize_t vp_lamp_show(struct device* dev, struct device_attribute* attr,  char* buf);  
    static ssize_t vp_lamp_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);  
      
    /*定义设备属性*/  
    static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, vp_lamp_show, vp_lamp_store);
     
     
    /*******************************************
    *define traditional file access 
    *******************************************/
    /*打开设备方法*/  
    static int vp_open(struct inode* inode, struct file* filp) {  
        struct vp_android_dev* dev;          
          
        /*将自定义设备结构体保存在文件指针的私有数据域中,以便访问设备时拿来用*/  
        dev = container_of(inode->i_cdev, struct vp_android_dev, dev);  
        filp->private_data = dev;  
          
        return 0;  
    }  
      
    /*设备文件释放时调用,空实现*/  
    static int vp_release(struct inode* inode, struct file* filp) {  
        return 0;  
    }  
      
    /*读取设备的寄存器val的值*/  
    static ssize_t vp_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {  
        ssize_t err = 0;  
        struct vp_android_dev* dev = filp->private_data;          
      
        /*同步访问*/  
        if(down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;  
        }  
      
        if(count < sizeof(dev->val)) {  
            goto out;  
        }          
      
        /*将寄存器val的值拷贝到用户提供的缓冲区*/  
        if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) {  
            err = -EFAULT;  
            goto out;  
        }  
      
        err = sizeof(dev->val);  
      
    out:  
        up(&(dev->sem));  
        return err;  
    }  
      
    /*写设备的寄存器值val*/  
    static ssize_t vp_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {  
        struct vp_android_dev* dev = filp->private_data;  
        ssize_t err = 0;          
      
        /*同步访问*/  
        if(down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;          
        }          
      
        if(count != sizeof(dev->val)) {  
            goto out;          
        }          
      
        /*将用户提供的缓冲区的值写到设备寄存器去*/  
        if(copy_from_user(&(dev->val), buf, count)) {  
            err = -EFAULT;  
            goto out;  
        }  
      
        err = sizeof(dev->val);  
      
    out:  
        up(&(dev->sem));  
        return err;  
    }  
     
     
    /*******************************************
    *define devfs access
    *******************************************/
    /*读取寄存器lamp的值到缓冲区buf中,内部使用*/  
    static ssize_t __vp_get_lamp(struct vp_android_dev* dev, char* buf) {  
        int lamp = 0;          
      
        /*同步访问*/  
        if(down_interruptible(&(dev->sem))) {                  
            return -ERESTARTSYS;          
        }          
      
        lamp = dev->lamp;          
        up(&(dev->sem));          
      
        return snprintf(buf, PAGE_SIZE, "%d\n", lamp);  
    }  
      
    /*把缓冲区buf的值写到设备寄存器lamp中去,内部使用*/  
    static ssize_t __vp_set_lamp(struct vp_android_dev* dev, const char* buf, size_t count) {  
        int lamp = 0;          
      
        /*将字符串转换成数字*/          
        lamp = simple_strtol(buf, NULL, 10);          
      
        /*同步访问*/          
        if(down_interruptible(&(dev->sem))) {                  
            return -ERESTARTSYS;          
        }          
      
        dev->lamp = lamp;          
        up(&(dev->sem));  
      
        return count;  
    }  
      
    /*读取设备属性lamp*/  
    static ssize_t vp_lamp_show(struct device* dev, struct device_attribute* attr, char* buf) {  
        struct vp_android_dev* hdev = (struct vp_android_dev*)dev_get_drvdata(dev);          
      
        return __vp_get_lamp(hdev, buf);  
    }  
      
    /*写设备属性lamp*/  
    static ssize_t vp_lamp_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {   
        struct vp_android_dev* hdev = (struct vp_android_dev*)dev_get_drvdata(dev);    
          
        return __vp_set_lamp(hdev, buf, count);  
    }  
     
     
    /*******************************************
    *define proc access
    *******************************************/
    /*读取设备寄存器lamp的值,保存在page缓冲区中*/  
    static ssize_t vp_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) {  
        if(off > 0) {  
            *eof = 1;  
            return 0;  
        }  
      
        return __vp_get_lamp(vp_dev, page);  
    }  
      
    /*把缓冲区的值buff保存到设备寄存器lamp中去*/  
    static ssize_t vp_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) {  
        int err = 0;  
        char* page = NULL;  
      
        if(len > PAGE_SIZE) {  
            printk(KERN_ALERT"The buff is too large: %lu.\n", len);  
            return -EFAULT;  
        }  
      
        page = (char*)__get_free_page(GFP_KERNEL);  
        if(!page) {                  
            printk(KERN_ALERT"Failed to alloc page.\n");  
            return -ENOMEM;  
        }          
      
        /*先把用户提供的缓冲区值拷贝到内核缓冲区中去*/  
        if(copy_from_user(page, buff, len)) {  
            printk(KERN_ALERT"Failed to copy buff from user.\n");                  
            err = -EFAULT;  
            goto out;  
        }  
      
        err = __vp_set_lamp(vp_dev, page, len);  
      
    out:  
        free_page((unsigned long)page);  
        return err;  
    }  
      
    /*创建/proc/vp文件*/  
    static void vp_create_proc(void) {
    struct proc_dir_entry *entry;
    entry = create_proc_entry(VP_DEVICE_PROC_NAME, 0, NULL);
    if(entry)
    {
    entry->read_proc = vp_proc_read;
    entry->write_proc = vp_proc_write;
    }
    }  
      
    /*删除/proc/vp文件*/  
    static void vp_remove_proc(void) {  
        remove_proc_entry(VP_DEVICE_PROC_NAME, NULL);  
    }  
     
     
    /*******************************************
    *define load and remove function
    *******************************************/
    /*初始化设备*/  
    static int  __vp_setup_dev(struct vp_android_dev* dev) {  
        int err;  
        dev_t devno = MKDEV(vp_major, vp_minor);  
      
        memset(dev, 0, sizeof(struct vp_android_dev));  
      
        cdev_init(&(dev->dev), &vp_fops);  
        dev->dev.owner = THIS_MODULE;  
        dev->dev.ops = &vp_fops;          
      
        /*注册字符设备*/  
        err = cdev_add(&(dev->dev),devno, 1);  
        if(err) {  
            return err;  
        }          
      
        /*初始化信号量和寄存器lamp, val的值*/  
        sema_init(&(dev->sem), 1);  
        dev->lamp = 7777;  
        dev->val.toggle = 1;  
        dev->val.virtual_latitude = 45.104108; 
        dev->val.virtual_longitude = 130.816878; 
     
        return 0;  
    }  
      
    /*模块加载方法*/  
    static int __init vp_init(void){   
        int err = -1;  
        dev_t dev = 0;  
        struct device* temp = NULL;  
      
        printk(KERN_ALERT"Initializing vp device.\n");          
      
        /*动态分配主设备和从设备号*/  
        err = alloc_chrdev_region(&dev, 0, 1, VP_DEVICE_NODE_NAME);  
        if(err < 0) {  
            printk(KERN_ALERT"Failed to alloc char dev region.\n");  
            goto fail;  
        }  
      
        vp_major = MAJOR(dev);  
        vp_minor = MINOR(dev);          
      
        /*分配helo设备结构体变量*/  
        vp_dev = kmalloc(sizeof(struct vp_android_dev), GFP_KERNEL);  
        if(!vp_dev) {  
            err = -ENOMEM;  
            printk(KERN_ALERT"Failed to alloc vp_dev.\n");  
            goto unregister;  
        }          
      
        /*初始化设备*/  
        err = __vp_setup_dev(vp_dev);  
        if(err) {  
            printk(KERN_ALERT"Failed to setup dev: %d.\n", err);  
            goto cleanup;  
        }          
      
        /*在/sys/class/目录下创建设备类别目录vp*/  
        vp_class = class_create(THIS_MODULE, VP_DEVICE_CLASS_NAME);  
        if(IS_ERR(vp_class)) {  
            err = PTR_ERR(vp_class);  
            printk(KERN_ALERT"Failed to create vp class.\n");  
            goto destroy_cdev;  
        }          
      
        /*在/dev/目录和/sys/class/vp目录下分别创建设备文件vp*/  
        temp = device_create(vp_class, NULL, dev, "%s", VP_DEVICE_FILE_NAME);  
        if(IS_ERR(temp)) {  
            err = PTR_ERR(temp);  
            printk(KERN_ALERT"Failed to create vp device.");  
            goto destroy_class;  
        }          
      
        /*在/sys/class/vp/vp目录下创建属性文件val*/  
        err = device_create_file(temp, &dev_attr_val);  
        if(err < 0) {  
            printk(KERN_ALERT"Failed to create attribute val.");                  
            goto destroy_device;  
        }  
      
        dev_set_drvdata(temp, vp_dev);          
      
        /*创建/proc/vp文件*/  
        vp_create_proc();  
      
        printk(KERN_ALERT"Succedded to initialize vp device.\n");  
        return 0;  
      
    destroy_device:  
        device_destroy(vp_class, dev);  
      
    destroy_class:  
        class_destroy(vp_class);  
      
    destroy_cdev:  
        cdev_del(&(vp_dev->dev));  
      
    cleanup:  
        kfree(vp_dev);  
      
    unregister:  
        unregister_chrdev_region(MKDEV(vp_major, vp_minor), 1);  
      
    fail:  
        return err;  
    }  
      
    /*模块卸载方法*/  
    static void __exit vp_exit(void) {  
        dev_t devno = MKDEV(vp_major, vp_minor);  
      
        printk(KERN_ALERT"Destroy vp device.\n");          
      
        /*删除/proc/vp文件*/  
        vp_remove_proc();          
      
        /*销毁设备类别和设备*/  
        if(vp_class) {  
            device_destroy(vp_class, MKDEV(vp_major, vp_minor));  
            class_destroy(vp_class);  
        }          
      
        /*删除字符设备和释放设备内存*/  
        if(vp_dev) {  
            cdev_del(&(vp_dev->dev));  
            kfree(vp_dev);  
        }          
      
        /*释放设备号*/  
        unregister_chrdev_region(devno, 1);  
    }  
      
    MODULE_LICENSE("GPL");  
    MODULE_DESCRIPTION("Virtualposition Driver");  
      
    module_init(vp_init);  
    module_exit(vp_exit);  


    添加 Kconfig 文件

    config VP
               tristate "Virtual Position Driver"
               default n
               help
               This is the virtual position driver.


    添加 Makefile 文件

    obj-$(CONFIG_VP) += vp.o


    修改 drivers/Kconfig 文件 在menu "Device Drivers"和endmenu之间添加一行:

    source "drivers/vp/Kconfig"  


    修改drivers/Makefile文件,添加一行:

    obj-$(CONFIG_HELLO) += vp/  


    修改 arch/arm/configs目录下的cyanogen_cancro_defconfig 文件,在文件末尾加入

    # CONFIG_VP
    CONFIG_VP=y

    =============分割线2==============
    第二步,修改HAL
    进入 ./hardware/libhardware/include/hardware 目录,新建 vp.h 文件

    #ifndef ANDROID_VP_INTERFACE_H  
    #define ANDROID_VP_INTERFACE_H  
    #include <hardware/hardware.h>  
    __BEGIN_DECLS  
      
    /*定义模块ID*/  
    #define VP_HARDWARE_MODULE_ID "vp"  
     
     
    //typedef enum{false, true} bool;
     
     
    /*define virtual position structrue*/
    typedef struct {
        int toggle;
        double virtual_latitude;
        double virtual_longitude;
    } VirtualPosition;
     
     
    /*硬件模块结构体*/  
    struct vp_module_t {  
        struct hw_module_t common;  
    };  
      
    /*硬件接口结构体*/  
    struct vp_device_t {  
        struct hw_device_t common;  
        int fd;  
        int (*set_val)(struct vp_device_t* dev, VirtualPosition val);  
        int (*get_val)(struct vp_device_t* dev, VirtualPosition* val);  
    };  
      
    __END_DECLS  
      
    #endif  


    进入到 hardware/libhardware/modules 目录,新建vp目录,并添加vp.c文件

    #define LOG_TAG "VpStub"  
      
    #include <hardware/hardware.h>  
    #include <hardware/vp.h>  
    #include <fcntl.h>  
    #include <errno.h>  
    #include <cutils/log.h>  
    #include <cutils/atomic.h>  
      
    #define DEVICE_NAME "/dev/vp"  
    #define MODULE_NAME "Vp"  
    #define MODULE_AUTHOR "aggresss@163.com"  
      
    /*设备打开和关闭接口*/  
    static int vp_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);  
    static int vp_device_close(struct hw_device_t* device);  
      
    /*设备访问接口*/  
    static int vp_set_val(struct vp_device_t* dev, VirtualPosition val);  
    static int vp_get_val(struct vp_device_t* dev, VirtualPosition* val);  
      
    /*模块方法表*/  
    static struct hw_module_methods_t vp_module_methods = {  
        open: vp_device_open  
    };  
      
    /*模块实例变量*/  
    struct vp_module_t HAL_MODULE_INFO_SYM = {  
        common: {  
            tag: HARDWARE_MODULE_TAG,  
            version_major: 1,  
            version_minor: 0,  
            id: VP_HARDWARE_MODULE_ID,  
            name: MODULE_NAME,  
            author: MODULE_AUTHOR,  
            methods: &vp_module_methods,  
        }  
    };  
     
     
     
     
    static int vp_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {  
        struct vp_device_t* dev;dev = (struct vp_device_t*)malloc(sizeof(struct vp_device_t));  
          
        if(!dev) {  
            ALOGE("Vp Stub: failed to alloc space");  
            return -EFAULT;  
        }  
      
        memset(dev, 0, sizeof(struct vp_device_t));  
        dev->common.tag = HARDWARE_DEVICE_TAG;  
        dev->common.version = 0;  
        dev->common.module = (hw_module_t*)module;  
        dev->common.close = vp_device_close;  
        dev->set_val = vp_set_val;dev->get_val = vp_get_val;  
      
        if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {  
            ALOGE("Vp Stub: failed to open /dev/vp -- %s.", strerror(errno));free(dev);  
            return -EFAULT;  
        }  
      
        *device = &(dev->common);  
        ALOGI("Vp Stub: open /dev/vp successfully.");  
      
        return 0;  
    }  
     
     
    static int vp_device_close(struct hw_device_t* device) {  
        struct vp_device_t* vp_device = (struct vp_device_t*)device;  
      
        if(vp_device) {  
            close(vp_device->fd);  
            free(vp_device);  
        }  
          
        return 0;  
    }  
      
    static int vp_set_val(struct vp_device_t* dev, VirtualPosition val) {  
        ALOGI("Vp Stub: set value %d to device.", val);  
      
        write(dev->fd, &val, sizeof(val));  
      
        return 0;  
    }  
      
    static int vp_get_val(struct vp_device_t* dev, VirtualPosition* val) {  
        if(!val) {  
            ALOGE("Vp Stub: error val pointer");  
            return -EFAULT;  
        }  
      
        read(dev->fd, val, sizeof(*val));  
      
        ALOGI("Vp Stub: get value %d from device", *val);  
      
        return 0;  
    }  


    继续在vp目录下新建Android.mk文件:

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE_TAGS := optional
    LOCAL_PRELINK_MODULE := false
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
    LOCAL_SHARED_LIBRARIES := liblog
    LOCAL_SRC_FILES := vp.c
    LOCAL_MODULE := vp.default
    include $(BUILD_SHARED_LIBRARY)

    =============分割线3==============
    第三步,修改JNI
    进入 frameworks/base/services/core/jni 目录,新建com_android_server_VirtualPositionService.cpp文件

    #define LOG_TAG "VirtualPositionService"  
    #include "jni.h"  
    #include "JNIHelp.h"  
    #include "android_runtime/AndroidRuntime.h"  
    #include <utils/misc.h>  
    #include <utils/Log.h>  
    #include <hardware/hardware.h>  
    #include <hardware/vp.h>  
    #include <stdio.h>  
     
     
    namespace android  
    {  
        
            VirtualPosition virtual_position = {1, 0.0, 0.0};
        /*在硬件抽象层中定义的硬件访问结构体,参考<hardware/vp.h>*/  
            struct vp_device_t* vp_device = NULL;  
        /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/  
            static void vp_setVal() {  
            ALOGI("VirtualPosition JNI: set value to device.");  
            if(!vp_device) {  
                ALOGI("VirtualPosition JNI: device is not open.");  
                return;  
            }  
              
            vp_device->set_val(vp_device, virtual_position);  
        }  
            /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/  
        static void vp_getVal() {  
            if(!vp_device) {  
                ALOGI("VirtualPosition JNI: device is not open.");  
            }  
            vp_device->get_val(vp_device, &virtual_position);  
              
            ALOGI("VirtualPosition JNI: get value from device.");  
        }  
            /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/  
        static inline int vp_device_open(const hw_module_t* module, struct vp_device_t** device) {  
            return module->methods->open(module, VP_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
        }  
            /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/  
        static jboolean vp_init(JNIEnv* env, jclass clazz) {  
            vp_module_t* module;  
              
            ALOGI("VirtualPosition JNI: initializing......");  
            if(hw_get_module(VP_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {  
                ALOGI("VirtualPosition JNI: vp Stub found.");  
                if(vp_device_open(&(module->common), &vp_device) == 0) {  
                    ALOGI("VirtualPosition JNI: vp device is open.");  
                    return 0;  
                }  
                ALOGE("VirtualPosition JNI: failed to open vp device.");  
                return -1;  
            }  
            ALOGE("VirtualPosition JNI: failed to get vp stub module.");  
            return -1;        
        }  
        
        static void android_server_VirtualPositionService_set_virtual_toggle(JNIEnv* env, jclass clazz, jint tog)
        {
            virtual_position.toggle = tog;
            vp_setVal();
        }
     
     
        static jint android_server_VirtualPositionService_get_virtual_toggle(JNIEnv* env, jclass clazz)
        {
            vp_getVal();
            return virtual_position.toggle;
        }
     
     
        static void android_server_VirtualPositionService_set_virtual_latitude(JNIEnv* env, jclass clazz, jdouble vlat)
        {
            virtual_position.virtual_latitude = vlat;
            vp_setVal();
        }
     
     
        static jdouble android_server_VirtualPositionService_get_virtual_latitude(JNIEnv* env, jclass clazz)
        {
            vp_getVal();
            return virtual_position.virtual_latitude;
        }
     
     
        static void android_server_VirtualPositionService_set_virtual_longitude(JNIEnv* env, jclass clazz, jdouble vlon)
        {
            virtual_position.virtual_longitude = vlon;
            vp_setVal();
        }
     
     
        static jdouble android_server_VirtualPositionService_get_virtual_longitude(JNIEnv* env, jclass clazz)
        {
            vp_getVal();
            return virtual_position.virtual_longitude;
        }
     
     
     
     
     
     
        /*JNI方法表*/  
        static const JNINativeMethod method_table[] = {  
            {"init_native",
                "()Z", 
                (void*)vp_init},  
            {"native_set_virtual_toggle",
                "(I)V",
                (void*)android_server_VirtualPositionService_set_virtual_toggle},
            {"native_get_virtual_toggle",
                "()I",
                (void*)android_server_VirtualPositionService_get_virtual_toggle},
            {"native_set_virtual_latitude",
                "(D)V",
                (void*)android_server_VirtualPositionService_set_virtual_latitude},
            {"native_get_virtual_latitude",
                "()D",
                (void*)android_server_VirtualPositionService_get_virtual_latitude},
            {"native_set_virtual_longitude",
                "(D)V",
                (void*)android_server_VirtualPositionService_set_virtual_longitude},
            {"native_get_virtual_longitude",
                "()D",
                (void*)android_server_VirtualPositionService_get_virtual_longitude},
     
     
        };  
            /*注册JNI方法*/  
        int register_android_server_VirtualPositionService(JNIEnv *env) {  
                return jniRegisterNativeMethods(env, "com/android/server/VirtualPositionService", method_table, NELEM(method_table));  
        }  
    };  


    修改同目录下的onload.cpp文件,首先在namespace android增加com_android_server_VirtualPositionService函数声明:

    namespace android {  
      
        ..............................................................................................  
      
        int register_android_server_VirtualPositionService(JNIEnv *env);  
      
        };  
    在JNI_onLoad增加register_android_server_VirtualPositionService函数调用:
    extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved)  
       {  
        .................................................................................................  
        register_android_server_VirtualPositionService(env);  
        .................................................................................................  
       }  


    修改同目录下的Android.mk文件,在LOCAL_SRC_FILES变量中增加一行:

    LOCAL_SRC_FILES:= \  
          com_android_server_AlarmManagerService.cpp \  
          com_android_server_BatteryService.cpp \  
          com_android_server_InputManager.cpp \  
          com_android_server_LightsService.cpp \  
          com_android_server_PowerManagerService.cpp \  
          com_android_server_SystemServer.cpp \  
          com_android_server_UsbService.cpp \  
          com_android_server_VibratorService.cpp \  
          com_android_server_location_GpsLocationProvider.cpp \  
          com_android_server_VirtualPositionService.cpp \ 
          onload.cpp  

    =============分割线4==============
    第四步,修改Framework
    进入到frameworks/base/core/java/android/os目录,新增VirtualPositionService.aidl接口定义文件

    package android.os;
     
     
    interface IVirtualPositionService {
        void setVirtualToggle(int tog);
        int getVirtualToggle();
        void setVirtualLatitude(double vlat);
        double getVirtualLatitude();
        void setVirtualLongitude(double vlon);
        double getVirtualLongitude();
    }


    然后进入 frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IVirtualPosition.aidl源文件:

    LOCAL_SRC_FILES += /
    ....................................................................
    core/java/android/os/IVibratorService.aidl /
    core/java/android/os/IVirtualPosition.aidl /
    core/java/android/service/urlrenderer/IUrlRendererService.aidl /
    .....................................................................


    进入到frameworks/base/services/java/com/android/server目录,新增VirtualPositionService.java文件

    package com.android.server;  
    import android.content.Context;  
    import android.os.IVirtualPositionService;  
    import android.util.Slog;  
     
     
    public class VirtualPositionService extends IVirtualPositionService.Stub {  
        private static final String TAG = "VirtualPositionService";  
        VirtualPositionService() {  
            init_native();  
        }  
        public void setVirtualToggle(int tog) {
            native_set_virtual_toggle(tog);
        }
     
     
        public int getVirtualToggle(){
            return native_get_virtual_toggle();
        }
     
     
        public void setVirtualLatitude(double vlat) {
            native_set_virtual_latitude(vlat);
        }
     
     
        public double getVirtualLatitude(){
            return native_get_virtual_latitude();
        }
     
     
        public void setVirtualLongitude(double vlon) {
            native_set_virtual_longitude(vlon);
        }
     
     
        public double getVirtualLongitude() {
            return native_get_virtual_longitude();
        }
        
        private static native boolean init_native();
        private static native void native_set_virtual_toggle(int tog);
        private static native int native_get_virtual_toggle();
        private static native void native_set_virtual_latitude(double vlat);
        private static native double native_get_virtual_latitude();
        private static native void native_set_virtual_longitude(double vlon);
        private static native double native_get_virtual_longitude();
     
     
    };  


    修改同目录的SystemServer.java文件,在ServerThread::run函数中增加加载VirtualPositionService的代码:

    
    @Override
    public void run() {
    ....................................................................................
    try {
    Slog.i(TAG, "DiskStats Service");
    ServiceManager.addService("diskstats", new DiskStatsService(context));
    } catch (Throwable e) {
    Slog.e(TAG, "Failure starting DiskStats Service", e);
    }
    try {
    Slog.i(TAG, "VirtualPosition Service");
    ServiceManager.addService("virtualposition", new VirtualPositionService());
    } catch (Throwable e) {
    Slog.e(TAG, "Failure starting VirtualPosition Service", e);
    }
    ......................................................................................
    } 


    然后需要修改sepolicy文件,具体的文件在github上,请下载使用。


    =============分割线5==============
    第五步,修改application
    APP的文件比较多,请到github上下载,这里只贴具体的逻辑代码:

    package com.example.phdemo.myapplication;
     
     
    import android.os.RemoteException;
    import android.app.Activity;
    import android.os.ServiceManager;
    import android.os.Bundle;
    import android.widget.CompoundButton;
    import android.os.IVirtualPositionService;
    import android.os.RemoteException;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ToggleButton;
    import android.widget.CompoundButton.OnCheckedChangeListener;
     
     
    public class MainActivity extends Activity implements View.OnClickListener {
     
     
        private final static String LOG_TAG = "com.example.phdemo.virtualposition";
     
     
        private IVirtualPositionService virtualpositionService = null;
    private ToggleButton toggleButton = null;
    private EditText altitudeValueText = null;
        private EditText longitudeValueText = null;
        private Button getButton = null;
        private Button setButton = null;
        private Button clearButton = null;
     
     
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
     
     
            virtualpositionService = IVirtualPositionService.Stub.asInterface(
                    ServiceManager.getService("virtualposition"));
     
     
            toggleButton=(ToggleButton)findViewById(R.id.toggleButton);
    altitudeValueText = (EditText)findViewById(R.id.altitude_value);
    longitudeValueText = (EditText)findViewById(R.id.longitude_value);
            getButton = (Button)findViewById(R.id.button_get);
            setButton = (Button)findViewById(R.id.button_set);
            clearButton = (Button)findViewById(R.id.button_clear);
            
            getButton.setOnClickListener(this);
            setButton.setOnClickListener(this);
            clearButton.setOnClickListener(this);
       
            try{ 
            int val_tog = virtualpositionService.getVirtualToggle();
                if(val_tog == 1){
                    toggleButton.setChecked(true);
                }else{
                    toggleButton.setChecked(false);
                }
            } catch (Exception e) {}
     
     
            toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener(){
    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
    toggleButton.setChecked(isChecked);
    try{
                        virtualpositionService.setVirtualToggle(isChecked?1:0);
                    }catch(Exception e){}
    }
    });
            Log.i(LOG_TAG, "VirtualPosition Activity Created");
        }
     
     
        @Override
        public void onClick(View v) {
            if(v.equals(getButton)) {
                try {
                    double val_altitude = virtualpositionService.getVirtualLatitude();
                    String text_altitude = String.valueOf(val_altitude);
                    altitudeValueText.setText(text_altitude);
    double val_longitude = virtualpositionService.getVirtualLongitude();
                    String text_longitude = String.valueOf(val_longitude);
                    longitudeValueText.setText(text_longitude);
    int val_tog = virtualpositionService.getVirtualToggle();
                    if(val_tog == 1){
                        toggleButton.setChecked(true);
                    }else{
                        toggleButton.setChecked(false);
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, "Remote Exception while reading value from GpsLocationProvider.");
                }
            }
            else if(v.equals(setButton)) {
                try {
                    String text_altitude = altitudeValueText.getText().toString();
    String text_longitude = longitudeValueText.getText().toString();
                    double val_altitude = Double.parseDouble(text_altitude);
    double val_longitude = Double.parseDouble(text_longitude);
                    virtualpositionService.setVirtualLatitude(val_altitude);
    virtualpositionService.setVirtualLongitude(val_longitude);
                } catch (Exception e) {
                    Log.e(LOG_TAG, "Remote Exception while writing value to GpsLocationProvider.");
                }
            }
            else if(v.equals(clearButton)) {
                String text = "";
                altitudeValueText.setText(text);
    longitudeValueText.setText(text);
            }
        }
    }

    =============分割线6==============
    最后一步,在JNI层面修改location report 机制。
    进入 frameworks/base/services/core/jni 目录,修改com_android_server_location_GpsLocationProvider.cpp文件:
    在全局变量部分加入

    // add by aggresss
    static int vp_fd = open("/dev/vp", O_RDWR); 
    static VirtualPosition vp_val;


    修改location_callback函数:

    static void location_callback(GpsLocation* location)
    {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        //add by aggresss
        read(vp_fd, &vp_val, sizeof(VirtualPosition));
        if(vp_val.toggle  == 1){
        env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
                (jdouble)vp_val.virtual_latitude, (jdouble)vp_val.virtual_longitude,
                (jdouble)location->altitude,
                (jfloat)location->speed, (jfloat)location->bearing,
                (jfloat)location->accuracy, (jlong)location->timestamp);
        checkAndClearExceptionFromCallback(env, __FUNCTION__);
        }
        else{
        env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
                (jdouble)location->latitude, (jdouble)location->longitude,
                (jdouble)location->altitude,
                (jfloat)location->speed, (jfloat)location->bearing,
                (jfloat)location->accuracy, (jlong)location->timestamp);
        checkAndClearExceptionFromCallback(env, __FUNCTION__);
        }
    }

    =============我是完成的分割线==============
    完成后,重新编译固件,开机后启动VirtualPosition的APP,设置你想要的坐标,想在哪就在哪了。
            
              

    展开全文
  • Android 图片属性信息修改(定位信息修改)无需root 直接获取手机中的图片的信息,并修改
  • 机 - 从源码着手任意修改GPS地理位置需求:随意修改定位android机过程中,经常会遇到随意修改位置GPS的需求。修改GPS的方式有很多种:xposed hookMockLocation修改源码以上三种方式都能修改gps随意修改gps坐标...

    改机 - 从源码着手任意修改GPS地理位置

    需求:随意修改定位

    android在改机过程中,经常会遇到随意修改位置GPS的需求。

    修改GPS的方式有很多种:

    xposed hook

    MockLocation

    修改源码

    以上三种方式都能修改gps随意修改gps坐标,各有优缺点:xposed隐藏不好,容易被发现;MockLocation容易在开发者模式和gps provider被识别;改源码,编译麻烦,而且不一定有源码;前两种方式具有普适性,改源码费时费力,局限性比较强;

    秉承明知山有虎,偏向虎上行的心态,尝试阅读以下android的源码,并且修改gps部分的代码;

    具体原理:切断hal层和framework之间的通讯,模仿硬件向framework通知硬件信息

    样例:android 8.0

    1. gps jni callbackstruct GnssCallback : public IGnssCallback {

    Return gnssLocationCb(

    const android::hardware::gnss::V1_0::GnssLocation& location) override; // gps位置变化回调函数

    Return gnssStatusCb(const IGnssCallback::GnssStatusValue status) override; // gps状态变化回调函数

    Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; // 卫星状态变化回调函数

    Return gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;

    Return gnssSetCapabilitesCb(uint32_t capabilities) override;

    Return gnssAcquireWakelockCb() override;

    Return gnssReleaseWakelockCb() override;

    Return gnssRequestTimeCb() override;

    Return gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    static GnssSvInfo sGnssSvList[static_cast(

    android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];

    static size_t sGnssSvListSize;

    static const char* sNmeaString;

    static size_t sNmeaStringLength;

    };

    // 省略......

    Return GnssCallback::gnssLocationCbImpl(const T& location) {

    JNIEnv* env = getJniEnv();

    jobject jLocation = translateGnssLocation(env, location);

    env->CallVoidMethod(mCallbacksObj,

    method_reportLocation, // frameworks

    boolToJbool(hasLatLong(location)),

    jLocation);

    checkAndClearExceptionFromCallback(env, __FUNCTION__);

    env->DeleteLocalRef(jLocation);

    return Void();

    }

    // 省略......

    method_reportLocation = env->GetMethodID(clazz, "reportLocation",

    "(ZLandroid/location/Location;)V");

    GnssCallback的作用就是在gps模块位置、状态、精度等信息变化后,通知上层应用的回调函数类。

    2. framework

    可以发现,在gps硬件模块拿到新的位置时,通知framework调用java的函数是reportLocation, 源码如下:

    /*

    * @hasLatLong: 地理位置是否合法

    * @loction: 地理位置

    */

    private void reportLocation(boolean hasLatLong, Location location) {

    if (location.hasSpeed()) {

    mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;

    }

    if (mItarSpeedLimitExceeded) {

    Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +

    " GPS/GNSS Navigation output blocked.");

    mGnssMetrics.logReceivedLocationStatus(false);

    return;

    }

    if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());

    synchronized (mLocation) {

    mLocation = location;

    // It would be nice to push the elapsed real-time timestamp

    // further down the stack, but this is still useful

    mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());

    mLocation.setExtras(mLocationExtras);

    try {

    mILocationManager.reportLocation(mLocation, false);

    } catch (RemoteException e) {

    Log.e(TAG, "RemoteException calling reportLocation");

    }

    }

    mGnssMetrics.logReceivedLocationStatus(hasLatLong);

    if (hasLatLong) {

    if (location.hasAccuracy()) {

    mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy());

    }

    if (mTimeToFirstFix > 0) {

    int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime);

    mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes);

    }

    }

    mLastFixTime = SystemClock.elapsedRealtime();

    // report time to first fix

    if (mTimeToFirstFix == 0 && hasLatLong) {

    mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);

    if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);

    mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix);

    // notify status listeners

    mListenerHelper.onFirstFix(mTimeToFirstFix);

    }

    if (mSingleShot) {

    stopNavigating();

    }

    if (mStarted && mStatus != LocationProvider.AVAILABLE) {

    // we want to time out if we do not receive a fix

    // within the time out and we are requesting infrequent fixes

    if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {

    mAlarmManager.cancel(mTimeoutIntent);

    }

    // send an intent to notify that the GPS is receiving fixes.

    Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);

    intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);

    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

    updateStatus(LocationProvider.AVAILABLE, mSvCount, mMeanCn0, mMaxCn0);

    }

    if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&

    mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {

    if (DEBUG) Log.d(TAG, "got fix, hibernating");

    hibernate();

    }

    }

    自此,刨除hal层,android系统就获取到了一个地理位置。原理了解后,就可以动手修改源码了。

    3. 切断hal层调用

    GnssLocationProvider.cpp

    #include

    // ....... 省略

    Return GnssCallback::gnssLocationCbImpl(const T& location) {

    // 定义一个系统开关,可以自由控制

    char property[PROP_VALUE_MAX];

    int len = __system_property_get("gps.location.custom", property);

    if(len > 0) {

    if(strcmp(property, "1") == 0) return Void();

    }

    // ...... 省略

    }

    4. 在framework中添加一个public函数

    LocationManager.java

    // ...... 省略

    public void reportCustomLocation(Location location) {

    mService.reportLocation(true, location);

    }

    5. 编译rommake update-api # 在LocationManager中添加了新的接口

    make -j32 # 炫耀一下我32核的的机器

    5. 在APK中使用

    MainActivity.java

    // ...... 省略

    Button btn = findViewById(R.id.test_btn);

    btn.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {

    try {

    Location l = new Location("gps");

    l.setLatitude(41.055962);

    l.setLongitude(110.307711);

    l.setAccuracy(2.0f);

    l.setTime(System.currentTimeMillis());

    l.setElapsedRealtimeNanos(System.currentTimeMillis());

    l.setAccuracy(1.0f);

    locationManager.reportCustomLocation(l);

    Location lo = locationManager.getLastKnownLocation(provider);

    Log.d(TAG, lo.toString());

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    });

    }

    最后于 2020-6-29 11:04

    被neocanable编辑

    ,原因: markdown 好像不太好用

    展开全文
  • Android支持地理定位服务的API。该地理定位服务可以用来获取当前设备的地理位置,应用程序可以定时请求更新设备当前的地理位置信息。比如应用程序可以借助一个Intent接收器来实现如下功能: 以经纬度和半径规划一个...
  • 最近试着写了一下Android定位,代码在下面,比较简单首先需要的权限有然后是里面的代码package com.example.a5.myapplication;import android.Manifest;import android.content.Context;import android.content.pm...

    最近试着写了一下Android的定位,代码在下面,比较简单

    首先需要的权限有

    然后是里面的代码

    package com.example.a5.myapplication;

    import android.Manifest;

    import android.content.Context;

    import android.content.pm.PackageManager;

    import android.location.Criteria;

    import android.location.Location;

    import android.location.LocationListener;

    import android.location.LocationManager;

    import android.support.v4.app.ActivityCompat;

    import android.support.v7.app.AlertDialog;

    import android.support.v7.app.AppCompatActivity;

    import android.os.Bundle;

    import android.view.View;

    import android.view.Window;

    import android.view.WindowManager;

    import android.webkit.WebView;

    import android.widget.Button;

    import android.widget.TextView;

    public class MainActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);

    //全屏

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

    WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.activity_main);

    Button button = (Button) findViewById(R.id.button);

    button.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    //获取位置服务

    LocationManager locationManager = (LocationManager) MainActivity.this.getSystemService(Context.LOCATION_SERVICE);

    Criteria criteria = new Criteria();

    //ACCURACY_HIGH/ACCURACY_LOW精度选择

    criteria.setAccuracy(Criteria.ACCURACY_FINE);

    //高度

    criteria.setAltitudeRequired(true);

    //方位信息

    criteria.setBearingRequired(true);

    //是否允许付费

    criteria.setCostAllowed(true);

    //对电量的要求

    criteria.setPowerRequirement(Criteria.POWER_LOW);

    //速度

    criteria.setSpeedRequired(true);

    //获取最佳服务

    String provider = locationManager.getBestProvider(criteria, true);

    //权限检查

    if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

    return;

    }

    //获取到了位置

    Location location = locationManager.getLastKnownLocation(provider);

    //开启地理位置监听定位类型、毫秒、米、监听时间

    locationManager.requestLocationUpdates(provider,3000,1,new listener());

    locateResult(location);

    }

    });

    }

    public class listener implements LocationListener {

    @Override

    public void onLocationChanged(Location location) {

    //位置变化,获取最新的位置

    locateResult(location);

    }

    @Override

    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override

    public void onProviderEnabled(String provider) {

    }

    @Override

    public void onProviderDisabled(String provider) {

    }

    }

    public void locateResult(Location location){

    new AlertDialog.Builder(MainActivity.this)

    .setMessage("纬度" + String.valueOf(location.getLatitude()) +

    "\n经度" + String.valueOf(location.getLongitude()) +

    "\n速度" + String.valueOf(location.getSpeed()) +

    "\n高度" + String.valueOf(location.getAltitude()) +

    "\n朝向" + String.valueOf(location.getBearing())

    )

    .setNegativeButton("取消",null)

    .show();

    }

    }

    最后上图:

    b2b069eddb816dfb57babc2556c1a258.gif

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • 修改安卓定位服务器地址 内容精选换一换安卓模拟器(Android Virtual Device),简称AVD,可以模拟安卓设备并将其运行在服务器上。利用AVD,您可以对安卓应用进行原型设计、开发和测试,而无需使用真实的手机。AVD具备...
  • Android中关于这几种定位都有具体的调用方法,所以如果想修改系统的定位信息,那么就必须先了解这几种调用方式,在之前的一篇文章中也说到了,Hook的最关键一点就是需要找到Hook的地方,这个就需要去阅读源码来...
  • 该项目基于开源库开发,并认识到Android设备OTG在连接到iPhone后可以修改iPhone的经度和纬度。 如果需要将可执行文件和库文件从开源项目移植到Android平台,则可以转到进行查看。 我整理了一些 感谢在开源项目问题...
  • 修改版---仿京东地址选择器一比一复刻,原理:viewpager+tablayout+view
  • 会编译android源码(如果你不愿意编译源码,还有另外一种办法,下面我会提供)2.会使用substrate或者xposed以上2个网上资料很多我就不啰嗦了一、市面上目前的hook和注入工具市面上目前的hook有substrate,xposed,或者...
  • 了解xposed框架,安装xposed框架并激活,打开此软件,设置想要修改的信息,然后选择应用,在xposed框架勾选,重启生效
  • gps定位,实测可用. 第一个是网络定位,第二个是GPS定位,第三个是直接取缓存。LocationManager本身提供了选择最好的provider的方法: // 获取最好的定位方式 String provider = locationManager....
  • android 模拟定位app 源码

    千次阅读 2021-06-07 12:43:38
    【实例简介】需要在android手机的 开发者模式中 开启 【允许模拟位置】即可,开启允许模拟位置的方法详见:...import android.app.Activity;import android...
  • android室内定位demo

    2014-09-10 10:30:12
    根据室内多个wifi信号的强度进行定位; 可以扫描室内wifi的型号强度Value,并记录到数据库。 目前还未完善:需要手动修改代码将记录的数据写入定位代码。 但大体定位能够成功,概率90%准确定位率; 基本算法已经可以...
  • 改变GPS定位实现Android模拟定位的方法,最近需要对微信,陌陌等程序进行位置模拟 实现世界各地发朋友圈,搜索附近人的功能,本着站在巨人肩膀上的原则 爱网上搜索一番,也找到一些 代码和文章,但是代码大都雷同...
  • gps 移动网络位置信息 ...\frameworks\base\services\core\java\com\android\server\location\GpsLocationProvider.java ro.wisky.gpssupport 此值设为 false 时不支持,则系统中一些有关 gps 的设置将会被...
  • android 免 root修改位置打卡

    万次阅读 2019-09-21 13:12:32
    Virtual Xponse(一个 类似于 android 虚拟机的东西, 可以将 android 软件 安装到里面, 或者也可以使用一些 xponse插件, ) 修改gps定位的软件。 你需要打卡的软件 将 修改 gps的软件, 与需要打卡的软件都安装在 ...
  • Android_Id、IMEI、手机序列号、手机号码、WIFI-MAC、WIFI-Name、安卓系统版本、ROM固件、手机号码、手机型号、手机品牌、CPU型号、手机制造商、GPS定位、通话记录模拟、手机短信模拟…… 等各类安卓手机系统信息的...
  • 一般我们使用的是第三...文章目录定位方式1.gps和network(时效性差)1.1 使用条件1.1.1 需要开启位置服务:1.1.2 安卓6.0以上还需要开启位置权限android.permission.ACCESS_COARSE_LOCATION,android.permission.ACC...
  • 该项目基于libimobiledevice开源库开发,并意识到Android设备OTG在连接到iPhone OTG之后可以修改iPhone的经度和纬度。该项目基于libimobiledevice开源库开发,并意识到连接到iPhone后,Android设备OTG可以修改iPhone...
  • Android 10 在2019年9月份正式发布,带来了一个非常重大的GPS权限改变。为用户提供了 仅在使用此应用时允许。一旦用户选择“仅在使用此应用时允许”,就会导致APP在后台或者锁屏时候无法正常记录GPS轨迹,这个对像...
  • uniapp 定位 android ios

    2021-09-02 15:00:01
    uniapp 定位 android ios <view class="cen-style"> <view class="cens-title">详细地址:</view> <view class="fbc"> <view style="width: 400rpx;"><u-input v-...
  • android模拟位置(修改)

    2014-12-11 22:38:21
    开启手机的模拟位置,获取位置和外网ip,并改变当前的手机经纬度,显示在界面中。在界面中绑定服务,在服务线程中不断的刷新修改的位置信息。
  • 安卓joy定位

    2019-02-21 13:39:22
    gpsjoystick安卓定位模拟可以打开隐私模式通过开启开发者权限
  • 一、定位内存中的修改点、 1、基址寻址法、 2、搜索定位法、
  • 项目使用了www.webxml.com.cn网站上的天气预报服务,需要把代码中的useid修改为自己的,另外项目使用了百度API实现了定位
  • Android定位功能实现

    万次阅读 多人点赞 2020-05-28 18:20:10
    关于Android定位功能如何实现的文章实在太多,有些文章着重于Android API的用法,有些则没有整个定位实现的完整流程,有些虽然有流程,但当你按照文章中的步骤实现好之后,很可能会发现各种问题,最常见的问题就是拿...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 79,321
精华内容 31,728
关键字:

安卓 怎么改定位