Android 相关笔记

1、对文件进行读写枷锁,使用了nio技术

RandomAccessFile randomFile = null;

        byte[] buf = new byte[1024]; 
        int count = 0; 
        try { 
            randomFile = new RandomAccessFile(new File(filePath), "rws"); 
            FileChannel channel = randomFile.getChannel(); 


            while ((count = is.read(buf)) > 0) { 
                FileLock lock = channel.tryLock(); 
                randomFile.write(buf, 0, count); 
                lock.release(); 
            } 
            return BitmapFactory.decodeFile(filePath); 
        } catch (IOException e) { 
            e.printStackTrace(); 
            return null; 
        } finally { 
            if (randomFile != null) 
                try { 
                    randomFile.close(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            closeStream(is, null); 
        }

2、当页面中需要横向滑动和纵向滑动时的时间判断机制:重写父view

public boolean onInterceptTouchEvent(MotionEvent ev) {

        final int action = ev.getAction();//获取触摸事件类型

        final float x = ev.getX();//每次触摸事件的x坐标

        final float y = ev.getY();//每次触摸事件的y坐标

        switch (action) {
        case MotionEvent.ACTION_DOWN://按下事件

            mLastMotionX = x;//初始化每次触摸事件的x方向的初始坐标,即手指按下的x方向坐标

            mLastMotionY = y;//初始化每次触摸事件的y方向的初始坐标,即手指按下的y方向坐标

            break;

 

        case MotionEvent.ACTION_MOVE:

            final intdeltaX = (int) (mLastMotionX - x);//每次滑动事件x方向坐标与触摸事件x方向初始坐标的距离

           final intdeltaY = (int) (mLastMotionY - y);//每次滑动事件y方向坐标与触摸事件y方向初始坐标的距离

            boolean xMoved = Math.abs(deltaX) > mTouchSlop && Math.abs(deltaY/deltaX) < 1;
            //判断触摸事件处理的传递方向,该业务中是,

            //x方向的距离大于手指,并且y方向滑动的距离小于x方向的滑动距离时,Gallery消费掉此次触摸事件

            //如果需要,请在您的业务中,改变判断的逻辑
            if (xMoved) {//Gallery需要消费掉此次触摸事件
                return true;//返回true就不会将此次触摸事件传递给子View了,我的业务中是ListView
            }

            break;

        }
        return false;//将此次触摸事件传递给子View,即ListView
    }

3、手机内存信息查看注释:

VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

4、查看单个应用内存使用情况命令:

查看单个应用程序内存占用量的命令:adb shell dumpsys meminfo [包名]|[进程号] 

5、外置SD卡和手机内置内存:

    public static File getDiskCacheDir(Context context, String uniqueName) {
        // 先检查外部存储是否挂载,如果挂载了,则使用外存,否则使用内存路径
        final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() : context.getCacheDir()
                .getPath();
        return new File(cachePath + File.separator + uniqueName);
    }

6、查看网络连接是否可用:

        final ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if(networkInfo == null || !networkInfo.isConnectedOrConnecting()){
            //提示用户设置网络:
            Toast.makeText(context, R.string.no_network_connection_toast , Toast.LENGTH_SHORT).show();
            Log.e(TAG, "checkConnection - no connection found");
        }

7、获取目前该手机能显示指定宽度图片多少列:

mImageThumbSize = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size);
mImageThumbSpacing = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_spacing);

int numColumns = (int) Math.floor(mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing));
//Adapter中这样设置:
       public int getCount() {
            // Size + number of columns for top empty row
            return Images.imageThumbUrls.length + mNumColumns;
        }


        public Object getItem(int position) {
            return position < mNumColumns ?
                    null : Images.imageThumbUrls[position - mNumColumns];
        }


        public long getItemId(int position) {
            return position < mNumColumns ? 0 : position - mNumColumns;
        }

8、图片下载缓存类使用方法:

先设置imageCacheParams
new ImageCacheParams(getActivity(), IMAGE_CACHE_DIR);
cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory
创建一个mImageFetcher
设置下载完成之前要显示的图片
添加到缓存 addImageCache();

对ListView的滑动状态进行监听
onScrollStateChange(){
if(scrollState == .SCROLL_STATE_FLING{
mImageFetcher.setPauseWork(true);
}else{
mImageFetcher.setPauseWork(false);
}
}
然后
onResume
mImageFetcher.setExitTasksEarly(false);

onPause
mImageFetcher.setExitTasksEarly(true);

onDestory()
mImageFetcher.colseCache();

mImageFetcher.setImageSize(height);
使用的时候:
mImageFetcher.loadImage(Images.imageThumbUrls[position - mNumColumns], imageView);


int numColumns = (int) Math.floor(
                                    mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing));

9、获取当前手机的宽高:

DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        final int height = displayMetrics.heightPixels;
        final int width = displayMetrics.widthPixels;

10、为了避免图片被重复下载,需要缓存图片。我可以通过获取头信息来保证我们的图片不过期(有效的缓存动态数据):

long currentTime = System.currentTimeMillis());

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

long expires = conn.getHeaderFieldDate("Expires", currentTime);
long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime);

setDataExpirationDate(expires);

if (lastModified < lastUpdateTime) {
  // Skip update
} else {
  // Parse update
}
11、获取Android系统app的缓存路径:
//外部缓存,用来缓存不敏感的数据,在Froyo之后
Context.getExternalCacheDir();
//内部缓存,是安全的应用程序缓存,但是当系统低可用存储的是该部分可能被刷新
Context.getCache();

//不论你将数据存储在那种缓存中,当应用程序卸载后该数据都将被清除。
/**
     * Get the external app cache directory.
     *
     * @param context The context to use
     * @return The external cache dir
     */
    @TargetApi(8)
    public static File getExternalCacheDir(Context context) {
        if (Utils.hasFroyo()) {
            return context.getExternalCacheDir();
        }


        // Before Froyo we need to construct the external cache dir ourselves
        final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
        return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
    }

12、关于HttpURLConnection Response Cache:在Android 4.0中添加了HttpURLConnection响应的缓存,你可以用HTTP响应,在支持设备上使用反射缓存数据:
private void enableHttpResponseCache() {
  try {
    long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
    File httpCacheDir = new File(getCacheDir(), "http");
    Class.forName("android.net.http.HttpResponseCache")
         .getMethod("install", File.class, long.class)
         .invoke(null, httpCacheDir, httpCacheSize);
  } catch (Exception httpResponseCacheNotAvailable) {
    Log.d(TAG, "HTTP response cache is unavailable.");
  }
}
上面的这段代码在4.0以上设备中将打开response cache,并且不影响其他低版本


13、查看指定路径还有多少空间可用:
/**
     * Check how much usable space is available at a given path.
     *
     * @param path The path to check
     * @return The space available in bytes
     */
    @TargetApi(9)
    public static long getUsableSpace(File path) {
        if (Utils.hasGingerbread()) {
            return path.getUsableSpace();
        }
        final StatFs stats = new StatFs(path.getPath());
        return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
    }
14、标准下载实例:
/**
     * Download something from a URL and write the content to an output stream.
     *
     * @param urlString The URL to fetch
     * @return true if successful, false otherwise
     */
    public boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
        disableConnectionReuseIfNecessary();
        HttpURLConnection urlConnection = null;
        BufferedOutputStream out = null;
        BufferedInputStream in = null;

        try {
            final URL url = new URL(urlString);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE);
            out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);

            int b;
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            return true;
        } catch (final IOException e) {
            Log.e(TAG, "Error in download- " + e);
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (final IOException e) {}
        }
        return false;
    }
/**
     * Workaround for bug pre-Froyo, see here for more info:
     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
     */
    public static void disableConnectionReuseIfNecessary() {
        // HTTP connection reuse which was buggy pre-froyo
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
            System.setProperty("http.keepAlive", "false");
        }
    }

15、Android屏幕解锁和点亮:
KeyguardManager  km= (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
//得到键盘锁管理器对象
KeyguardLock kl = km.newKeyguardLock("unLock");
//参数是LogCat里用的Tag
kl.disableKeyguard(); //解锁
PowerManager pm=(PowerManager) getSystemService(Context.POWER_SERVICE);//获取电源管理器对象
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright");
//获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag
wl.acquire();//点亮屏幕
wl.release();//释放

//需要的权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

16、查看android每帧的绘制时间:
    在android4.1之上,setting->developter options->Force Gpu rendering。如果开发者选项在你的4.2设备上不可见,你可以在“关于手机”或者“关于桌面选择”的界面底部,点击“版本号”七次。(真的可以?)打开这个选项之后,系统将会记录每个窗口绘画最后128帧需要的时间。在使用这个工具前,你得先杀掉这个应用(Android未来版本将会去掉这个要求)。然后重新启动这个应用并滚动时间轴主界面时。在终端运行一下命令:

$ adb shell dumpsys gfxinfo packagename
将标记为Profile的毫秒级的数据,这段数据包含了一个有三列数据的表,应用的每个window都有一个这样的表,为了使用这个数据,你可以简单的讲这个表拷贝到你喜欢的电子制表软件中,从而生成一个数据堆叠的列图。每一列给出了每一帧花在渲染上的时间估计:

“Draw”是指Java层用在创建“display lists”(显示列表)上的时间。它表明运行例如View.onDraw(Canvas)需要多少时间。
 “Process”是指Android 2D渲染引擎用在执行“display lists”上的时间。你的UI层级(hierarchy)中的View数量越多,需要执行的绘画命令就越多。
 “Execute”是指将一帧图像交给合成器(compositor)的时间。这部分占用的时间通常比较少
以60fps的帧率进行平滑的渲染,每一帧所占用的时间需要要少于16ms


17、也可以使用Systrace来检查问题,setting->developer options->Enable traces->在dialog中选择要监视的项目,比如Graphics、View。不要忘记关闭profile GPU rendering。然后在tools/systrace目录下,运行$./sysytrace.py这个工具默认会记录5秒内发生的事情。可以看到一个用HTML文档展现结果。

18、开启GPU视图更新之后,色块代表的意思:
如果你记得每种颜色所表示的含义,你就能很容易的知道结果是什么:

没有颜色就表示没有重绘。每个像素只画了一次。在这个例子里,你可以看到背景是完全无色的。
蓝色:表示重绘了一次。每个像素只画了两次。大块的蓝色是可以接受的。(如果整个window是蓝色的,你就可以使用一个图层(layer)。)
绿色:表示重绘了两次。每个像素画了三次。中等尺寸的绿色方块是可以接受的,但你最好尝试做出优化。
红色:表示重绘了三次。这个像素被画了四次。很小尺寸的红色方块是可以接受的。
黑色:表示重绘了四次及以上。这个像素被画了五次及以上。这个是错的,需要解决。
基于这些信息,你可以看到“设置”应用表现地很好,不需要额外的改进。只有在切换时有一点点红块,但不需要我们再做什么工作了。

19、当作为第三方包时,检查当前应用是否包含某权限(访问网络的权限):

Context.checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED

你可能感兴趣的:(Android 相关笔记)