总结Ubuntu上使用Android SDK开发经验

 更新时间:2016年9月20日 19:58  点击:1614
本文来分享我在Ubuntu使用Android SDK开发经验的几点总结,测试环境为:Ubuntu 12.04 x86_64,ADT Bundle Linux x86_64 。

测试硬件环境:

打开了Intel VT的PC (使用KVM时需要VT支持的)

测试软件环境:

Ubuntu 12.04 x86_64

ADT Bundle Linux x86_64 (在android官网下载:https://developer.android.com/sdk/index.html )

1. 下载所需的Image和创建AVD:

可以在Eclipse(ADT)中,”Window” -> “Andorid SDK Manager”来打开SDK管理器进行下载,需要下载相应版本(如Android 4.2.2/4.3)的SDK Platform及其对应的ARM或Intel x86 Atom的系统镜像(如果要在Intel PC上使用Emulator并且要使用KVM加速,则一定需要下载Intel x86 Atom的系统镜像)。另外,由于SDK Manager是默认到google.com的一些网站下载相关的信息,如果发现有连接不上的情况(原因你懂的),可以通过”Tools”->”Options”中设置你自己的代理。

在Eclipse-ADT中,”Window” -> “Andorid Virtual Device Manager” 来打开AVD管理器,在上面可以创建自己的AVD文件,注意:如果要在Intel平台上使用KVM加速,则创建AVD时,对CPU/ABI的选择是 “Intel Atom (x86)”。

另外,如果使用一些程序时,其定义的API没有找到,就需要自己下载了;比如,当前有Android API 18 SDK,可能某个程序需要API 17,就需要下载Android 17的SDK了。

2. KVM加速:

我们都知道,运行Android Emulator时很慢的,有时慢到难以忍受。

如果在Android Emulaor中使用了KVM,则可以实现启动和运行时程序的加速,效果可能提高5~10倍的执行速度;记得用x86那种AVD。

一些命令行操作如下:

 代码如下 复制代码
jay@jay-linux:~$ sudo modprobe kvm
jay@jay-linux:~$ sudo modprobe kvm_intel
 
jay@jay-linux:~$ lsmod | grep kvm
kvm_intel             137721  0
kvm                   415550  1 kvm_intel
 
jay@jay-linux:~$ ps -ef | grep emulator | grep -v grep
jay      11749 10704 14 19:48 pts/18   00:02:18 /home/jay/adt-bundle-linux-x86_64-20130917/sdk//tools/emulator64-x86 -avd Android-4.2-x86 -scale 0.23
 
jay@jay-linux:~$ lsmod | grep kvm
kvm_intel             137721  3
kvm                   415550  1 kvm_intel
# 可看使用Emualtor后,kvm_intel模块已经有3个引用了。

3. OpenGL ES:

如果有OpenGL ES的支持,则可以在Emulator中有更好的图像处理能力,比如:可以运行一些3D的程序。

当本机缺少或ADT没找到OpenGL相关的库时,会遇到如下的错误。

 代码如下 复制代码
[2013-10-10 18:34:19 - App2] Launching a new emulator with Virtual Device 'Android-4.2-x86'
[2013-10-10 18:34:26 - Emulator] Failed to load libGL.so
[2013-10-10 18:34:26 - Emulator] error libGL.so: cannot open shared object file: No such file or directory
[2013-10-10 18:34:26 - Emulator] Failed to load libGL.so
[2013-10-10 18:34:26 - Emulator] error libGL.so: cannot open shared object file: No such file or directory
[2013-10-10 18:34:26 - Emulator] emulator: emulator window was out of view and was recentered

解决方法也很简单,一般来说都是有了库的,只是需要添加一个软连接而已;有时,库也缺少,那么就需要先安装GL相关的软件库,再建立软连接。

 代码如下 复制代码
# 如果在/usr/lib下找不到libGL相关的东西,可以用 sudo apt-get install libgl1-mesa-glx  来安装相应的软件库。
jay@jay-linux:~$ ll /usr/lib/x86_64-linux-gnu/mesa/
total 428
drwxr-xr-x  2 root root   4096 Sep  3 17:56 ./
drwxr-xr-x 54 root root  36864 Oct 10 15:07 ../
-rw-r--r--  1 root root     31 Jun 19 04:54 ld.so.conf
lrwxrwxrwx  1 root root     12 Jun 19 04:54 libGL.so.1 -> libGL.so.1.2
-rw-r--r--  1 root root 390352 Jun 19 04:55 libGL.so.1.2
# 可以看到刚好没有libGL.so,就在 /usr/lib/x86_64-linux-gnu/mesa/ 目录下,建立一个指向libGL.so.1.2的软连接libGL.so即可
# 如果没有root权限,则可以在SDK的lib目录中建立软连接亦可,如下所示:
jay@jay-linux:~$ ln -s /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2 /home/jay/adt-bundle-linux-x86_64-20130917/sdk/tools/lib/libGL.so

下面来为各位介绍一个关于Android优化双缓存的图片异步加载工具(LruCache+SoftReference)例子,希望对大家有帮助.


之前在郭大神的博客看到使用LruCache算法实现图片缓存的.这里仿效他的思路,自己也写了一个. 并加入ConcurrentHashMap<String, SoftReference<Bitmap>>去实现二级缓存,因为ConcurrentHashMap是多个锁的线程安全,支持高并发.很适合这种频繁访问读取内存的操作.


下面整个思路是,使用了系统提供的LruCache类做一级缓存, 大小为运行内存的1/8,当LruCache容量要满的时候,会自动将系统移除的图片放到二级缓存中,但为了避免OOM的问题,这里将SoftReference软引用加入来,当系统快要OOM的时候会自动清除里面的图片内存,当然内存充足时就会继续保存这些二级缓存的图片.强调一点,不要用SoftReference去做一级缓存,现在的java中垃圾回收加强了对SoftReference软引用的回收机制,它只适合临时的保存一些数据缓存,并不适合长期的(相对临时而言,并不是真正的长期).


直接上代码,拿来即用哦:

/**
 * Created on 3/11/2015
 * <br>图片异步加载工具(支持本地图片加载,网络图片URL和项目内图片资源加载)
 * <br>支持双缓存: LruCache和SoftReference
 * @author Mr.Et
 *
 */
public class ImageLoadManager {
 /** 图片源类型: 文件,网络,资源ID **/
 public enum IMAGE_LOAD_TYPE
 {
  FILE_PATH,FILE_URL,FILE_RESOURCE_ID
 }
 
 private String TAG = "ImageLoadManager...";
 
 private Context context;
 
 private Set<ImageLoadTask> taskCollection;
 
 /** 最大内存 **/
 final static int maxCacheSize = (int)(Runtime.getRuntime().maxMemory() / 8);
 
 /** 建立线程安全,支持高并发的容器 **/
 private static ConcurrentHashMap<String, SoftReference<Bitmap>> currentHashmap
  = new ConcurrentHashMap<String, SoftReference<Bitmap>>();
 
 
 
 
 
 
 
 public ImageLoadManager(Context context)
 {
  super();
  this.context = context;
  taskCollection = new HashSet<ImageLoadManager.ImageLoadTask>();
 }
 
 private static LruCache<String, Bitmap> BitmapMemoryCache = new LruCache<String, Bitmap>(maxCacheSize)
 {
  @Override
  protected int sizeOf(String key, Bitmap value)
  {
   if(value != null)
   {
    return value.getByteCount();
    //return value.getRowBytes() * value.getHeight(); //旧版本的方法
   }
   else
   {
    return 0;
   }
  }
  
  //这个方法当LruCache的内存容量满的时候会调用,将oldValue的元素移除出来腾出空间给新的元素加入
  @Override
  protected void entryRemoved(boolean evicted, String key,Bitmap oldValue, Bitmap newValue)
  {
   if(oldValue != null)
   {
    // 当硬引用缓存容量已满时,会使用LRU算法将最近没有被使用的图片转入软引用缓存   
    currentHashmap.put(key, new SoftReference<Bitmap>(oldValue));
   }
  }
  
 };
 
 /**
  * 针对提供图片资源ID来显示图片的方法
  * @param loadType 图片加载类型
  * @param imageResourceID 图片资源id
  * @param imageView 显示图片的ImageView
  */
 public void setImageView(IMAGE_LOAD_TYPE loadType, int imageResourceID, ImageView imageView)
 {
  if(loadType == IMAGE_LOAD_TYPE.FILE_RESOURCE_ID)
  {
//   if(ifResourceIdExist(imageResourceID))
//   {
//    imageView.setImageResource(imageResourceID);
//    
//   }else{ //映射无法获取该图片,则显示默认图片
//    imageView.setImageResource(R.drawable.pic_default);
//   }
   try
   {
    imageView.setImageResource(imageResourceID);
    return;
   } catch (Exception e) {
    Log.e(TAG, "Can find the imageID of "+imageResourceID);
    e.printStackTrace();
   }
   //默认图片
   imageView.setImageResource(R.drawable.pic_default);
  }
 }
 
 /**
  * 针对提供图片文件链接或下载链接来显示图片的方法
  * @param loadType  图片加载类型
  * @param imageFilePath 图片文件的本地文件地址或网络URL的下载链接
  * @param imageView 显示图片的ImageView
  */
 public void setImageView(IMAGE_LOAD_TYPE loadType, String imageFilePath, ImageView imageView)
 {
  if(imageFilePath == null || imageFilePath.trim().equals(""))
  {
   imageView.setImageResource(R.drawable.pic_default);
   
  }else{
   Bitmap bitmap = getBitmapFromMemoryCache(imageFilePath);
   if(bitmap != null)
   {
    imageView.setImageBitmap(bitmap);
   }
   else
   {
    imageView.setImageResource(R.drawable.pic_default);
    ImageLoadTask task = new ImageLoadTask(loadType, imageView);
    taskCollection.add(task);
    task.execute(imageFilePath);
   }
  }
 }
 
 /**
  * 从LruCache中获取一张图片,如果不存在就返回null
  * @param key  键值可以是图片文件的filePath,可以是图片URL地址
  * @return Bitmap对象,或者null
  */
 public Bitmap getBitmapFromMemoryCache(String key)
 { 
  try
  {
   if(BitmapMemoryCache.get(key) == null)
   {
    if(currentHashmap.get(key) != null)
    {
     return currentHashmap.get(key).get();
    }
   }
   return BitmapMemoryCache.get(key);
   
  } catch (Exception e) {
   e.printStackTrace();
  }
  return BitmapMemoryCache.get(key);
 }
 
 /**
  * 将图片放入缓存
  * @param key
  * @param bitmap
  */
 private void addBitmapToCache(String key, Bitmap bitmap)
 {
  BitmapMemoryCache.put(key, bitmap);
 }
 
 
 /**
  * 图片异步加载
  * @author Mr.Et
  *
  */
 private class ImageLoadTask extends AsyncTask<String, Void, Bitmap>
 {
  private String imagePath;
  private ImageView imageView;
  private IMAGE_LOAD_TYPE loadType;
  
  public ImageLoadTask(IMAGE_LOAD_TYPE loadType , ImageView imageView)
  {
   this.loadType = loadType;
   this.imageView = imageView;
  }
  
  @Override
  protected Bitmap doInBackground(String...params)
  {
   imagePath = params[0];
   try
   {
    if(loadType == IMAGE_LOAD_TYPE.FILE_PATH)
    {
     if(new File(imagePath).exists())
     { //从本地FILE读取图片
      BitmapFactory.Options opts = new BitmapFactory.Options();
      opts.inSampleSize = 2;
      Bitmap bitmap = BitmapFactory.decodeFile(imagePath, opts);
      //将获取的新图片放入缓存
      addBitmapToCache(imagePath, bitmap);
      return bitmap;
     }
     return null;
    }
    else if(loadType == IMAGE_LOAD_TYPE.FILE_URL)
    { //从网络下载图片
     byte[] datas = getBytesOfBitMap(imagePath);
     if(datas != null)
     {
//      BitmapFactory.Options opts = new BitmapFactory.Options();
//      opts.inSampleSize = 2;
//      Bitmap bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length, opts);
      Bitmap bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length);
      addBitmapToCache(imagePath, bitmap);
      return bitmap;
     }
     return null;
    }
    
   } catch (Exception e) {
    e.printStackTrace();
    FileUtils.saveExceptionLog(e);
    //可自定义其他操作
   }
   return null;
  }
  
  @Override
  protected void onPostExecute(Bitmap bitmap)
  {
   try
   {
    if(imageView != null)
    {
     if(bitmap != null)
     {
      imageView.setImageBitmap(bitmap);
     }
     else
     {
      Log.e(TAG, "The bitmap result is null...");
     }
    }
    else
    {
     Log.e(TAG, "The imageView is null...");
     //获取图片失败时显示默认图片
     imageView.setImageResource(R.drawable.pic_default);
    }
    
   } catch (Exception e) {
    e.printStackTrace();
    FileUtils.saveExceptionLog(e);
   }
  }
  
  
 }
 
 
 /**
  * InputStream转byte[]
  * @param inStream
  * @return
  * @throws Exception
  */
 private byte[] readStream(InputStream inStream) throws Exception{ 
        ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
        byte[] buffer = new byte[2048]; 
        int len = 0; 
        while( (len=inStream.read(buffer)) != -1){ 
            outStream.write(buffer, 0, len); 
        } 
        outStream.close(); 
        inStream.close(); 
        return outStream.toByteArray(); 
    }
 
 /**
  * 获取下载图片并转为byte[]
  * @param urlStr
  * @return
  */
 private byte[] getBytesOfBitMap(String imgUrl){
  try {
   URL url = new URL(imgUrl);
   HttpURLConnection conn = (HttpURLConnection) url.openConnection();
   conn.setConnectTimeout(10 * 1000);  //10s
   conn.setReadTimeout(20 * 1000);
         conn.setRequestMethod("GET"); 
         conn.connect();
         InputStream in = conn.getInputStream();
         return readStream(in);
  } catch (IOException e) {
   e.printStackTrace();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return null;
 }
 
 /**
  * 该资源ID是否有效
  * @param resourceId 资源ID
  * @return
  */
 private boolean ifResourceIdExist(int resourceId)
 {
  try
  {
   Field field = R.drawable.class.getField(String.valueOf(resourceId));
   Integer.parseInt(field.get(null).toString());
   return true;
   
  } catch (Exception e) {
   e.printStackTrace();
  }
  return false;
 }
 
 /**
  * 取消所有任务
  */
 public void cancelAllTask()
 {
  if(taskCollection != null){
   for(ImageLoadTask task : taskCollection)
   {
    task.cancel(false);
   }
  }
 }
 
 
}

In addition, 如果需要更加完美的体验,还可以加入第三级的缓存机制, 比如将图片缓存到本地的磁盘存储空间中.但是又不想这些缓存在本地的图片被其他应用扫描到或者被用户看到怎么办? 这里有几个思路, 比如将图片用加密算法转为字符串存储,或者将图片转为自定义格式的未知文件去放在隐蔽的地方(很多应用都采取了这种方式). 这个不妨自己去尝试实现哦~

在eclipse中并不能直接开发android程序,需要一个ADT插件,但在64位Ubuntu上,Eclipse中使用ADT时,提示R找不到“R cannot be resolved to a variable”错误,如何解决呢?

在64位Ubuntu上,Eclipse中使用ADT查看Andorid App 代码时,发现很多都时红的(错误),提示为R找不到“R cannot be resolved to a variable”。

我们都知道R.java时自动生成的,通过R可以引用App中的resource。

同时,仔细一看,在gen/my.package/下并没有自动生成R.java文件。

其原因,应该是自动生成R.java的工具的运行需要32bit的一些库,而在64bit系统上默认可能缺少这些库。

解决方案也很简单,直接安装所需的库即可,例如在Ubuntu上:

 代码如下 复制代码
jay@jay-linux:~$ sudo apt-get install ia32-libs



安装好32bit的库后,刷新项目或重启Eclipse后,就正常了。

Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。

周末试玩了一下在Eclipse中使用ADT开发Android应用程序的环境,当然诚如大家都懂的那样,Android Emulator模拟器启动和运行的速度确实是比较慢的,也都“有口皆碑”了的,呵呵。当然,Intel去年开发并在Google Android官方网站发布了一个对Android Emulator的驱动,大幅提升了在Intel x86平台上Android Emulator的启动和运行效率,从而提升Android应用程序开发者在使用Android模拟器开发程序时的效率。
在Windows、MacOS上使用HAXM (Hardware Accelerated Execution Manager) 来加速Android Emulator,在Linux平台上直接使用KVM加速即可。据官方介绍,一般来说使用了HAXM或KVM,有5~10x的性能提高,我简单看了下确实也有几倍的提高。
HAXM必须要求有Intel硬件虚拟化的支持,一般在BIOS中可以设置。BTW,ThinkPad X230的BIOS中,居然是在Security选项中设置VT的。
可以通过Android SDK Manager那下载HAXM, 在 Package 列表的最下面就是要用到的 Intel HAXM 扩展 (Intel x86 Emulator Accelerator (HAXM)),也需要安装对应的Image(Intel x86 Atom System Image)。下载后的HAXM安装文件在sdkextrasintelHardware_Accelerated_Execution_Manager 目录下,点击安装即可(注意如果Intel VT没有打开是不能安装成功的)。

在制作AVD时,需要设置其“CPU/ABI”属性为“Intel Atom (x86)”。对于图形方面的加速,编辑AVD设置时,Emulation Option选择“Use Host GPU”。

Android Virtual Device Manager中启动某个某个AVD时,可能会看到如下:

Starting emulator for AVD 'AVD_for_Nexus_S_by_Google'
emulator: device fd:620
HAX is working and emulator runs in fast virt mode
creating window 0 0 438 729

Eclipse中ADT运行时,对应的输出如下(可以看到HAX是否work):

[2013-07-08 11:44:43 - JayFirstApp] ------------------------------
[2013-07-08 11:44:43 - JayFirstApp] Android Launch!
[2013-07-08 11:44:43 - JayFirstApp] adb is running normally.
[2013-07-08 11:44:43 - JayFirstApp] Performing com.example.jayfirstapp.MainActivity activity launch
[2013-07-08 11:44:43 - JayFirstApp] Automatic Target Mode: launching new emulator with compatible AVD 'AVD_for_Nexus_S_by_Google'
[2013-07-08 11:44:43 - JayFirstApp] Launching a new emulator with Virtual Device 'AVD_for_Nexus_S_by_Google'
[2013-07-08 11:44:47 - Emulator] emulator: device fd:620
[2013-07-08 11:44:47 - Emulator]
[2013-07-08 11:44:47 - Emulator] HAX is working and emulator runs in fast virt mode
[2013-07-08 11:44:50 - Emulator] creating window 0 0 438 729
[2013-07-08 11:44:50 - JayFirstApp] New emulator found: emulator-5554
[2013-07-08 11:44:50 - JayFirstApp] Waiting for HOME ('android.process.acore') to be launched...

BTW,HAXM是我们Team开发的,如果大家使用时遇到什么bug,也可以反馈给我,我可转交给HAXM的developer。 (Update:本人不在那个team,请大家有问题到Intel HAXM官方网站去反馈吧: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager)

使用 Intel HAXM 为 Android 模拟器加速,媲美真机

Intel HAXM (Hardware Accelerated Execution Manager) 使用基于 Intel(R) Virtualization Technology (VT) 的硬件加速, 因此需要 CPU 支持 VT , 而且仅限于 Intel CPU, 与 AMD CPU 无缘, Intel HAXM 的描述如下:

使用 Intel VT 技术;

为 Android x86 虚拟设备的模拟运行提供硬件加速;

与 Android SDK 集成;

硬件需求如下:

支持 VT-x, EM64T 以及 Execute Disable Bit 的 Intel 处理器;

至少 1GB 可用内存

支持的操作系统:

Windows 7 (32/64-bit)

Windows Vista (32/64-bit)

Windows XP (32-bit only)

OS X 10.6 or 10.7 (32/64-bit)

下载并安装 Intel HAXM 扩展

启动 Android SDK Manager, 在 Package 列表的最下面就是要用到的 Intel HAXM 扩展, 打勾, 下载, 不用去 Intel 的网站, 如下图:

 

下载并安装 Intel HAXM 扩展

 

下载 HAXM 之后, 需要运行安装程序来进行安装, HAXM 下载的目录是 android-sdk\extras\intel\Hardware_Accelerated_Execution_Manager , 运行 IntelHaxm.exe 进行安装, 根据屏幕提示,一步一步安装即可。

下载 Android x86 镜像

Android SDK Manager 中已经有了 4.1.2 的 x86 镜像, 因此选择 4.1.2 x86 镜像, 如下图所示:

 

下载 Android x86 镜像

 

使用 Android x86 镜像

新建或者编辑 Android 模拟器, 将模拟器 CPU/ABI 设置为 Intel Atom X86 , 如下图所示:

 

配置 Android 模拟器使用 x86 系统镜像

 

如果上面的步骤都没有出错, 现在, Android 模拟器运行的速度几乎可以媲美真机了, 再也不用羡慕 MAC 平台上的 iOS 模拟器。

张志敏所有文章遵循创作共用版权协议,要求署名、非商业 、保持一致。在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处。

在Android开发中,测试完全模拟人为点击时输入中文比较麻烦,不过我们可以用 MonkeyRunner 自动输入中文字符,下面我们来分享这个的实现方法。

在做一些Android自动化脚本,比如向手机QQ中输入中文聊天内容,由于使用Robotium、Appium等工具来做时,由于TX作了签名校验的,所以登录不了QQ的。后来只能使用最傻的MonkeyRunner来做,不过它是完全模拟人为点击,而数据中文就很麻烦了。为此我们尝试了多种方案,简单分享一下:

1. 通过PC的剪贴板与Android模拟器中共享来实现:先将要输入的中文放到PC的剪贴板中,再到Android模拟器中粘贴到QQ聊天输入框中。其缺点是,很不稳定,有时候成功,有时候比较莫名的失败。

2. adb shell input 命令可直接将字符串输入到Android应用的Input框中,但问题来了,它不支持unicode字符啊(仅支持ASICC字符)。于是,我根据网上资料找到了一个方法:使用unicode字符原样输出,然后再转化为encoded字符。比如:https://github.com/bingwei/inputchineseviaadb,就实现了这样的转换,在app中复制到android的剪贴板中,然后可以在QQ聊天框等地方粘贴就好了。当然这里他这个gitlab项目中utils/inputunicode.py文件有点小bug,对于python 2.x,需要在adb shell input后跟的string用encode(‘unicode-escape’)编码。
这个种方式的速度不是很快,不过还是算不错的,因为本来做UI自动化耽误个一两秒钟也是可以接受的;我们最终就是采用了这种方案,目前运行下来是非常稳定的。

3. 使用一个外部REST服务器,搞一个key-value对放到REST sever中,其中key是全英文的,而value中可以包含中文;然后通过adb shell input将key传入到Andoid中,在Android中根据key去请求远程REST API从而得到包含中文字符的Value。没试过这种方法,不过应该是可行的;但其效率估计比第2中方法还要效率低下。

4. 一种专门为unicode做的输入法,可以adb shell input输入unicode,它帮你转成中文之类的字符。没真正尝试过。

[!--infotagslink--]

相关文章

  • 图解PHP使用Zend Guard 6.0加密方法教程

    有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • ps怎么使用HSL面板

    ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。 &#8195;...2017-07-06
  • Plesk控制面板新手使用手册总结

    许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
  • 使用insertAfter()方法在现有元素后添加一个新元素

    复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • jQuery 1.9使用$.support替代$.browser的使用方法

    jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 使用percona-toolkit操作MySQL的实用命令小结

    1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24
  • 使用GruntJS构建Web程序之构建篇

    大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
  • 如何使用php脚本给html中引用的js和css路径打上版本号

    在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24
  • MySQL日志分析软件mysqlsla的安装和使用教程

    一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈,需要的朋友可以参考一下...2020-06-25
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 安装和使用percona-toolkit来辅助操作MySQL的基本教程

    一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • php语言中使用json的技巧及json的实现代码详解

    目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30