Attempted to finish an input event but the ~~~异常

来源:互联网 发布:江苏老快三遗漏数据 编辑:程序博客网 时间:2024/06/08 05:47

  • 04-8 06:36:48.372: W/InputEventReceiver(7867): Attempted to finish an input event but the input event receiver has already been disposed.04-8 06:36:48.372: W/InputEventReceiver(7867): Attempted to finish an input event but the input event receiver has already been disposed.04-8 06:36:48.372: I/Choreographer(7867): Skipped 87 frames!  The application may be doing too much work on its main thread.04-8 06:36:48.372: W/ViewRootImpl(7867): Dropping event due to root view being removed: MotionEvent { action=ACTION_UP, id[0]=0, x[0]=287.0, y[0]=-358.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5442878, downTime=5442722, deviceId=0, source=0x1002 }04-8 06:37:31.392: I/uploadFile(7867): HTTP Response is : Internal Server Error: 50001-18 06:37:31.522: E/Async Time(7867): Async entered POSTTTT

    这是源码:

    private class ImageUploadTask extends AsyncTask<String, Void, String> {        private String webAddressToPost = "http://10.0.2.2:3000/wardrobe";        // File sourceFile = new File(imageview);        String fileName = "/sdcard/IMG_2016.JPG";        File sourceFile = new File(fileName );        HttpURLConnection conn = null;        DataOutputStream dos = null;        String lineEnd = "\r\n";        String twoHyphens = "--";        String boundary = "*****";        int bytesRead, bytesAvailable, bufferSize;        byte[] buffer;        int maxBufferSize = 1 * 1024 * 1024;        // private ProgressDialog dialog        private ProgressDialog progressDialog = new ProgressDialog(                wardrobe.this);        @Override        protected void onPreExecute() {            Log.e("Async Time", "Async entered 1 PREEE");            progressDialog.setMessage("Uploading...");            progressDialog.show();        }        @Override        protected String doInBackground(String... arg0) {            Log.e("Async Time", "Async entered DURINGG");            try {                // open a URL connection to the Servlet                FileInputStream fileInputStream = new FileInputStream(                        sourceFile);                URL url = new URL(webAddressToPost);                // Open a HTTP connection to the URL                conn = (HttpURLConnection) url.openConnection();                conn.setDoInput(true); // Allow Inputs                conn.setDoOutput(true); // Allow Outputs                conn.setUseCaches(false); // Don't use a Cached Copy                conn.setRequestMethod("POST");                conn.setRequestProperty("Connection", "Keep-Alive");                conn.setRequestProperty("ENCTYPE", "multipart/form-data");                conn.setRequestProperty("Content-Type",                        "multipart/form-data;boundary=" + boundary);                conn.setRequestProperty("uploaded_file", fileName);                dos = new DataOutputStream(conn.getOutputStream());                dos.writeBytes(twoHyphens + boundary + lineEnd);                dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""                        + fileName + "\"" + lineEnd);                dos.writeBytes(lineEnd);                // create a buffer of maximum size                bytesAvailable = fileInputStream.available();                bufferSize = Math.min(bytesAvailable, maxBufferSize);                buffer = new byte[bufferSize];                // read file and write it into form...                bytesRead = fileInputStream.read(buffer, 0, bufferSize);                while (bytesRead > 0) {                    dos.write(buffer, 0, bufferSize);                    bytesAvailable = fileInputStream.available();                    bufferSize = Math.min(bytesAvailable, maxBufferSize);                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);                }                // send multipart form data necesssary after file data...                dos.writeBytes(lineEnd);                dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);                // Responses from the server (code and message)                serverResponseCode = conn.getResponseCode();                String serverResponseMessage = conn.getResponseMessage();                Log.i("uploadFile", "HTTP Response is : "                        + serverResponseMessage + ": " + serverResponseCode);                if (serverResponseCode == 200) {                    String msg = "File Upload Completed.\n\n See uploaded file here : \n\n"                            + " F:/wamp/wamp/www/uploads";                    imageTextSelect.setText(msg);                    Toast.makeText(wardrobe.this, "File Upload Complete.",                            Toast.LENGTH_SHORT).show();                }                // close the streams //                fileInputStream.close();                dos.flush();                dos.close();            } catch (Exception e) {                e.printStackTrace();            }            return null;        }        @Override        protected void onPostExecute(String result) {            Log.e("Async Time", "Async entered POSTTTT");            progressDialog.dismiss();            Toast.makeText(getApplicationContext(), "file uploaded",                    Toast.LENGTH_LONG).show();        }    }

    解决办法:

    将String fileName = "/sdcard/IMG_2016.JPG"; 改为:

    String fileName = Environment.getExternalStorageDirectory().getAbsolutePath() +                             "/IMG_2016.JPG";







    发布于 1年前, 阅读(3965) | 评论(0) | 投票(0) | 收藏(0) 阅读全文...
  • Failed to load JavaHL Library(windows和mac)

    分类: Anroid开发
    092014-04

    一,windows下:

    在windows是64位的电脑中,安装好svn后,把项目提交到svn的过程中,总是弹出来一个错误的对话框: 
    Failed to load JavaHL Library.  
    These are the errors that were encountered:  
    从网上查看了一下解决办法, 
    1.选择window--->preferences->Team->SVN->SVN接口 
    2.选择SVNKit (Pure Java) xxxxxx 

    如下图所示 
     
    重启之后就不会再报错了。

      二,mac下:

      解决方法

      1.选择Eclipse--->preferences->Team->SVN->SVN接口 
      2.选择SVNKit (Pure Java) xxxxxx 

      发布于 1年前, 阅读(2092) | 评论(0) | 投票(0) | 收藏(3) 阅读全文...
    • Android的多种屏幕适配

      分类: Anroid开发
      082014-04


      一、Android支持的多种屏幕

      传统意义上,一般是是这么认为的:

      ldpi: 对应分辨率240×320

      mdpi: 对应分辨率320×480

      hdpi:对应分辨率480×800或480×854

      但实际上没有这么简单,直接看官方资料的下标,可以看到其实ldpi一样由480×800,甚至还有1024×600


      低密度(ldpi 120)中密度(mdpi 160)高密度(hdpi 240)超高密度(320 xhdpi)小屏幕QVGA (240×320)
      480×640
      中屏幕WQVGA400 (240×400)
      WQVGA432 (240×432)HVGA (320×480)WVGA800 (480×800)
      WVGA854 (480×854)
      600×1024640×960大屏幕WVGA800** (480×800)
      WVGA854** (480×854)WVGA800* (480×800)
      WVGA854* (480×854)
      600×1024

      超大屏幕1024×600WXGA (1280×800)
      1024×768
      1280×7681536×1152
      1920×1152
      1920×12002048×1536
      2560×1536
      2560×1600

      二、如何分辨是ldpi、mdpi、hdpi?

      为什么要分辨率ldpi、mdpi、hdpi?我的理解,是为了要在不同的屏幕密度下取得最好的显示效果。

      从上一段来看,通过分辨率来看并不是很靠谱,那怎么样才靠谱?其实,只要我们知道屏幕分辨率、屏幕尺寸(对角线长度),就可以算出相应的屏幕密度,从而根据其范围得出属于那种屏幕密度。

      我们可以根据长或者根据宽来计算出dpi,计算公式为:

      dpi=宽/((尺寸^2 * 宽^2)/(宽^2 + 高^2))^(1/2)

      = 长/((尺寸^2 * 长^2)/(宽^2 + 高^2))^(1/2)

      此计算公式可以在excel中予以计算。

      大概计算方法如下,以宽为例:

      1.比如分辨率为320×480,则长宽比为1:1.5

      2.比如屏幕尺寸为3.6”,则根据勾股定理,”长^2+宽^2=3.6^2″,即”宽^2+2.25*宽^2=12.96″,得出”宽^2=12.96/3.25″,则”宽=(12.96/3.25)^(1/2)= 1.9969″

      3.宽为320px,分布在1.9969”上,因此密度为320/1.9969=160.2467

      4.因此此密度为mdpi的密度

      注:

      1.此部分参考文章为:http://blog.sina.com.cn/s/blog_7377a8a20100qydh.html

      2.两款计算dpi的应用

      https://market.android.com/details?id=appinventor.ai_wenjiun1024.DPICalculato

      https://market.android.com/details?id=com.andy.dpi

      三、粗略的分辨率ldpi 、mdpi、hdpi

      套用老资料,其实传统意义上的通过分辨率判断手机dpi,还是比较靠谱的:

      ldpi: 对应分辨率240×320

      mdpi: 对应分辨率320×480

      hdpi:对应分辨率480×800或480×854

      为什么呢?因为ldpi如果要是320×480,则需要4.8寸的屏幕,如果是480×800,则需要7.8寸的屏幕,如果mdpi是480×800,则需要5.2寸的屏幕,一般的手机屏幕不会这么大,所以还算靠谱。

      当然,如果是分辨android pad的dpi,建议还是算一下吧。

      四、如何适配之9-patch?

      官方资料:http://developer.android.com/guide/developing/tools/draw9patch.html

      简单来说,如果你的图片资源是可以拉伸的而不会变形或者模糊的,则完全可以使用9-patch的格式,而不用为不同的dpi提供不同的图片资源。

      此格式经常用在背景性质的图片资源中。

      android开发包提供了9-patch的制作工具,上方的划线指明横向可以拉伸的区域,左方的划线指明纵向可以拉伸的区域,下方的划线指明水平居中的区域,右方的划线指明垂直居中的区域。

      在盆地的理解中,一般提供hdpi大小的图片,并制作为9-patch格式,此时的拉伸在mdpi、ldpi上基本都不会带来问题。

      这部分网上有不少资料,这里就不再赘述了,上述的描述是为了盆地日后便于想起和理解。

      五、如何适配指图标和其他图片

      除了指明拉伸区域拉伸不变形的图片外,类似图标或者其他会变形的图片资源,最佳情况下需要分别针对不同的dpi提供不同的图片。

      此处特别需要注意的是,假设不考虑xhdpi的支持,hdpi、mdpi、ldpi的支持,需要考虑相应的比例,即1.5:1:0.75,需要在相应比例关系下保持整数的像素值,否则可能会产生模糊的情况。

      举个具体例子,某个图标在hdpi下大小为48×48,则mdpi和ldpi下分别为32×32和24×24,如果此图标在hdpi设定为50×50,则mdpi下50无法整除1.5,因此mdpi下图标不论图标设定为33×33还是34×34都会模糊(可能独立指定可以避免此情况,此部分不太了解)。

      六、菜单图标和应用图标

      这一部分在官方资料中描述的很全面,只是不少应用开发者没有按照规范来,比如桌面图标的在hdpi上分辨率虽然定义的是72×72,但实际上应该只占60×60(如果是正方形,则应该是56×56),而不少应用直接把图标设定为72×72,所以会发现android中很多图标比系统的图标大一些,就是这个缘故。

      这一部分就直接参照官方文档吧,做法上也就是做三份,只是需要遵照文档来。

      http://developer.android.com/guide/practices/ui_guidelines/icon_design.ht


      发布于 1年前, 阅读(20) | 评论(0) | 投票(0) | 收藏(0) 阅读全文...
    • 解决AsyncTask引发的RejectedExecutionException

      分类: Anroid开发
      082014-04

      AsyncTask是google为易用和有效的异步操作UI线程的所开发的一个封装类。使用者可以很轻易的使用其进行后台操作,然后将结果传给UI线程,而不需要使用Thread和Handler。

      这样好用的一个类,显然可以在ListView异步加载图片时大显身手,本着这样的想法,笔者瞬间就完成了一段这样的模拟代码:

      Adapter的getView方法:


       1         @Override  2         public View getView(int pos, View view, ViewGroup viewGroup) {  3             if (view == null) {  4                 view = getLayoutInflater().inflate(R.layout.test2_list_item,  5                         null);  6             }  7             ImageView imageView = (ImageView) view.findViewById(R.id.imageView);  8             //这里每次都new出一个新的AsyncTask,进行执行。  9             new TestAsyncTask(imageView, pos).execute(new Object()); 10             TextView itemView = (TextView) view.findViewById(R.id.itemView); 11             itemView.setText("测试数据" + pos); 12             return view; 13         }


      TestAsyncTask:


       1 private class TestAsyncTask extends AsyncTask {  2         private ImageView imageView;  3         private int index;  4   5         public TestAsyncTask(ImageView imageView, int index) {  6             this.imageView = imageView;  7             this.index = index;  8         }  9  10         @Override 11         protected Object doInBackground(Object... arg0) { 12             // 模拟长时间的运算;大多数情况下是等待进行网络请求。 13             long sum = 0; 14             for (int i = 0; i <= 10000 * 100; i++) { 15                 sum += i * 1l; 16             } 17             return null; 18         } 19  20         @Override 21         protected void onPostExecute(Object result) { 22             //模拟已经获得了网络请求的图片 23             imageView.setImageBitmap(BitmapFactory.decodeResource( 24                     getResources(), R.drawable.image01, null)); 25         } 26     }


      运行调试,图片一个一个全都加载出来,没有问题,正当我疯狂的向下翻动着,妄图享受一下列表迅速滑动的快感的时候,一个无情的错误弹了出来。

      04-17 11:22:52.009: E/AndroidRuntime(22792): FATAL EXCEPTION: main
      04-17 11:22:52.009: E/AndroidRuntime(22792): java.util.concurrent.RejectedExecutionException: pool=128/128, queue=10/10
      04-17 11:22:52.009: E/AndroidRuntime(22792): at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1961)
      04-17 11:22:52.009: E/AndroidRuntime(22792): at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794)
      04-17 11:22:52.009: E/AndroidRuntime(22792): at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1315)

      好吧,现在我理解为啥网络上流传的异步加载图片是用更加繁琐的Thread加Handler形式,而不用AsyncTask了。

      难道是AsyncTask有什么用法上的问题,从出错结果来看貌似是达到了某个上限被拒绝了。那我们就从这个java.util.concurrent.RejectedExecutionException错误入手。

      翻看java的在线文档RejectedExecutionException,我们看到了这个错误的解释


      public class RejectedExecutionExceptionextends RuntimeException
      Exception thrown by an Executor when a task cannot be accepted for execution.Since:1.5See Also:Serialized Form


      这个表明是Executor这个类不接受执行task时抛出的异常。而Executor是java1.5之后增加的java.util.concurrent包中操作多线程的主要类。可以执行多个RunnableTask,看来google的AsyncTask就是用的这套API。

      了解到这点,我们就可以打开AsyncTask的源码查看它到底是怎么实现的:

      打开源码之后,找到execute方法: 


       1     /**  2      * Executes the task with the specified parameters. The task returns  3      * itself (this) so that the caller can keep a reference to it. 4      *  5      * This method must be invoked on the UI thread.  6      *  7      * @param params The parameters of the task.  8      *  9      * @return This instance of AsyncTask. 10      * 11      * @throws IllegalStateException If {@link #getStatus()} returns either 12      *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. 13      */ 14     public final AsyncTask<Params, Progress, Result> execute(Params... params) { 15         if (mStatus != Status.PENDING) { 16             switch (mStatus) { 17                 case RUNNING: 18                     throw new IllegalStateException("Cannot execute task:" 19                             + " the task is already running."); 20                 case FINISHED: 21                     throw new IllegalStateException("Cannot execute task:" 22                             + " the task has already been executed " 23                             + "(a task can be executed only once)"); 24             } 25         } 26  27         mStatus = Status.RUNNING; 28  29         onPreExecute(); 30  31         mWorker.mParams = params; 32         sExecutor.execute(mFuture); 33  34         return this; 35     }


       找到这里使用的ExecutorsExecutor这个属性,这样来到它赋值的地方


       1     private static final String LOG_TAG = "AsyncTask";  2   3     private static final int CORE_POOL_SIZE = 5;  4     private static final int MAXIMUM_POOL_SIZE = 128;  5     private static final int KEEP_ALIVE = 10;  6   7     private static final BlockingQueue<Runnable> sWorkQueue =  8             new LinkedBlockingQueue<Runnable>(10);  9  10     private static final ThreadFactory sThreadFactory = new ThreadFactory() { 11         private final AtomicInteger mCount = new AtomicInteger(1); 12  13         public Thread newThread(Runnable r) { 14             return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); 15         } 16     }; 17  18     private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, 19             MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);


      可以看到他是构造了一个ThreadPoolExecutor常量,保证new出多个AsyncTask都是使用这一个Executor。异常应该是它抛出的,我们看下这个类的文档,其中有一段是这样描述的:


      Rejected tasks New tasks submitted in method execute(Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated. In either case, the execute method invokes the rejectedExecution(Runnable, ThreadPoolExecutor) method of its         RejectedExecutionHandler. Four predefined handler policies are provided:
        1.In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.  2.In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow    down the rate that new tasks are submitted.  3.In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.  4.In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried     (which can fail again, causing this to be repeated.)
      It is possible to define and use other kinds of RejectedExecutionHandler classes. Doing so requires some care especially when policies are designed to work only under particular capacity or queuing policies.

       原来在Executor的队列和容量都达到最大时,再次增加新的task的时候将会进行拒绝行为,而默认的拒绝行为就是抛出这个RejectedExecutionException异常。

       看到这里顿时恍然了,原来初始化ThreadPoolExecutor没有指定拒绝行为,导致了异常的发生。google,你可以的!

       那解决方案也就诞生了,就是复制一份AsyncTask的源码,自己重写这个初始化方法,增加相应的拒绝策略,后面就有几个可供选择的策略。修改AsyncTask源码如下

      1     private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,2             MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());

      再次运行,OK,不会再抛出那个异常了。

      其实当你看AsyncTask的google官方文档时,你会发现后面有这么一段:

      Order of execution


      When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

      也就是说刚开始,AsyncTask是被限制在一个线程里。从1.6开始,使用了线程池,允许运行多任务同时进行。而到了3.0之后,又被限制在一个线程里为了避免多线程执行的错误。

      变3次了,你可以的,google。

      为了验证这段话,瞅瞅3.0之后的AsyncTask的源码:


          private static final String LOG_TAG = "AsyncTask";        private static final int CORE_POOL_SIZE = 5;        private static final int MAXIMUM_POOL_SIZE = 128;        private static final int KEEP_ALIVE = 1;       private static final ThreadFactory sThreadFactory = new ThreadFactory() {            private final AtomicInteger mCount = new AtomicInteger(1);            public Thread newThread(Runnable r) {                return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());        }    };        private static final BlockingQueue<Runnable> sPoolWorkQueue =                new LinkedBlockingQueue<Runnable>(10);    /**     * An {@link Executor} that can be used to execute tasks in parallel.     */    public static final Executor THREAD_POOL_EXECUTOR                = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);    /**     * An {@link Executor} that executes tasks one at a time in serial     * order.  This serialization is global to a particular process.     */     public static final Executor SERIAL_EXECUTOR = new SerialExecutor();        private static final int MESSAGE_POST_RESULT = 0x1;        private static final int MESSAGE_POST_PROGRESS = 0x2;         private static final InternalHandler sHandler = new InternalHandler();    //这里我们发现到了这个默认的执行器,是下面实现的线性队列。         private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;         private final WorkerRunnable<Params, Result> mWorker;         private final FutureTask<Result> mFuture;         private volatile Status mStatus = Status.PENDING;         private final AtomicBoolean mCancelled = new AtomicBoolean();         private final AtomicBoolean mTaskInvoked = new AtomicBoolean();         private static class SerialExecutor implements Executor {             final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();        Runnable mActive;               public synchronized void execute(final Runnable r) {            mTasks.offer(new Runnable() {                            public void run() {                                try {                        r.run();                    } finally {                        scheduleNext();                    }                }            });                        if (mActive == null) {                scheduleNext();            }        }                protected synchronized void scheduleNext() {                    if ((mActive = mTasks.poll()) != null) {                THREAD_POOL_EXECUTOR.execute(mActive);            }        }    }


       这样我们也就可以根据3.0的源码修改我们的AsyncTask里的默认执行器,同样使用SerialExecutor保证只会启用一个线程。另外3.0的AsyncTask多了一个executeOnExecutor(java.util.concurrent.Executor, Object[])方法,如果你希望有多个任务同时启动,也可以使用THREAD_POOL_EXECUTOR执行。


      发布于 1年前, 阅读(23) | 评论(0) | 投票(0) | 收藏(1) 阅读全文...
    • Android报unable to instantiate application怎么解决?

      分类: Anroid开发
      052014-04

      Android应用程序启动的时候,后台可能会报unable to instantiate application异常

      以下是原因分析和解决方法:

       可能原因1:   

        <application
              android:name="com.ershouhuowang.activity.MyApplication"
              android:allowBackup="true"
              android:icon="@drawable/ic_launcher"
              android:label="@string/app_name"
              android:theme="@style/AppTheme" >

      解决方法1

      AndroidManifest.xml中的application里的android:name去掉

       

      可能原因2:

      全局类 private 或者 变量private

      解决方法2

      将全局类 或者 变量 修改为public

       

      可能原因3:

      package 路径错误

      解决方法3

      package路径修改正确

       

      可能原因4:

      String mStrKey = getString(R.string.baidu_map_key);

      在Application类里从strings文件获取字符串会报空点异常

      解决方法4

      在Application类里不要从strings文件获取字符串 


      可能原因5:

      java编译器版本不兼容

      解决方法:

      把1.7的jdk换为1.6


      可能原因6:

      sdk升级后,文件错误

      解决方法:

      使用sdk 17以上的版本时,将lib重命名为libs





      发布于 1年前, 阅读(1224) | 评论(0) | 投票(0) | 收藏(2) 阅读全文...
    • 子线程调用Toast报Can't create handler inside ~~~ 错误

      分类: Anroid开发
      042014-04

      今天用子线程调Toast报了一个Can't create handler inside thread that has not calledLooper.prepare()错误。在网上找了找答案,发现两篇文章:


      【1】http://czhjchina.blog.163.com/blog/static/20027904720123163149186/


      因为toast的现实需要在activity的主线程才能正常工作,所以传统的线程不能使toast显示在actvity上,通过Handler可以使自定义线程运行于Ui主线程

      前几次碰到这个问题,确实郁闷了很久... log -- java.lang.RuntimeException: Can't create handler inside thread that has not calledLooper.prepare()

      解决办法很简单:
              Looper.prepare();

      Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();

      Looper.loop();


      为什么要加这两句,看了源码就了解了
      Toast 
          public void show() {
            ...
              service.enqueueToast(pkg, tn, mDuration);   //把这个toast插入到一个队列里面
              ...
          }

      Looper
      public static final void prepare() {
              if (sThreadLocal.get() != null) {
                  throw new RuntimeException("Only one Looper may be created per thread");
              }
             sThreadLocal.set(new Looper());  //在当前线程中创建一个Looper
          }

      private Looper() {
              mQueue = new MessageQueue();  //关键在这,创建Looper都干了什么。 其实是创建了消息队列
              mRun = true;
              mThread = Thread.currentThread();
          }


      一般如果不是在主线程中又开启了新线程的话,一般都会碰到这个问题。
      原因是在创建新线程的时候默认情况下不会去创建新的MessageQueue。


      总结下:Toast 显示的必要条件:
      1:Toast 显示需要出现在一个线程的消息队列中.... 很隐蔽



      【2】http://tech.cncms.com/shouji/android/96016.html


      Android中HandlerThread类的解释


       Android应用中的消息循环由Looper和Handler配合完成,Looper类用于封装消息循环,类中有个MessageQueue消息队列;Handler类封装了消息投递和消息处理等功能。

      系统默认情况下只有主线程(即UI线程)绑定Looper对象,因此在主线程中可以直接创建Handler的实例,但是在子线程中就不能直接new出Handler的实例了,因为子线程默认并没有Looper对象,此时会抛出RuntimeException异常:

      浏览下Handler的默认构造函数就一目了然了:

       

      如果需要在子线程中使用Handler类,首先需要创建Looper类实例,这时可以通过Looper.prepare()和Looper.loop()函数来实现的。阅读Framework层源码发现,Android为我们提供了一个HandlerThread类,该类继承Thread类,并使用上面两个函数创建Looper对象,而且使用wait/notifyAll解决了多线程中子线程1获取子线程2的Looper对象为空的问题。




      第一篇文章的处理方法是对的,但是解释应该是第二篇文章所说的,Toast创建时需要创建一个Handler,但是这个Handler需要获得Looper的实例,而在子线程中是没有这个实例的,需要手动创建。


      附Toast部分源码:


          public Toast(Context context) {
              mContext = context;
              mTN = new TN();
              mTN.mY = context.getResources().getDimensionPixelSize(
                      com.android.internal.R.dimen.toast_y_offset);
          }


          private static class TN extends ITransientNotification.Stub {
              ……
              final Handler mHandler = new Handler();    

              ……

          }


      Handler源码:


          /**
           * Default constructor associates this handler with the queue for the
           * current thread.
           *
           * If there isn't one, this handler won't be able to receive messages.
           */
          public Handler() {
              if (FIND_POTENTIAL_LEAKS) {
                  final Class<? extends Handler> klass = getClass();
                  if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                          (klass.getModifiers() & Modifier.STATIC) == 0) {
                      Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                          klass.getCanonicalName());
                  }
              }

              mLooper = Looper.myLooper();
              if (mLooper == null) {
                  throw new RuntimeException(
                      "Can't create handler inside thread that has not called Looper.prepare()");
              }
              mQueue = mLooper.mQueue;
              mCallback = null;
          }


      发布于 1年前, 阅读(1189) | 评论(1) | 投票(0) | 收藏(2) 阅读全文...
    • Mac下android_sdk配置环境变量

      分类: Anroid开发
      012014-04

      下面我将一下mac环境下的配置步骤: 

      1.启动Terminal终端工具
      2.输入cd ~/ 进入当前用户的home目录

      3. 创建:

      touch .bash_profile

      4.打开并编辑:

      open .bash_profile

      5、在文件中写入以下内容:export PATH=${PATH}:/Users/sxpmg/Application/android-sdk-mac_x86/tools:/Users/sxpmg/Application/android-sdk-mac_x86/platform-tools 
      其中:/Users/sxpmg/Application/android-sdk-mac_x86/tools不是固定的,它指向android SDK的tools目录,/Users/sxpmg/Application/android-sdk-mac_x86/platform-tools指向android SDK的platform-tools目录,也是根据具体情况而定。这只是我配置的时候所用的路径而已。 
      6、执行如下命令:source .bash_profile 
      7、验证:输入adb回车。如果未显示command not found,说明此命令有效,环境便亮设置完成。


      发布于 1年前, 阅读(53) | 评论(0) | 投票(0) | 收藏(0) 阅读全文...
    • Ant打包

      分类: Anroid开发
      312014-03

      通常我们习惯用eclipse来开发Android程序,它会自动帮我们打包当前的应用程序。如果在Navigator视图下,我们可以看到以下几个文件:

      在上图中,com包放置的是我们的class文件,classes.dex是class文件经过转换后的可以在dalvik上跑的精简类文件,resources.ap_是经过打包的资源文件,ant.apk就是最终的打包文件。

      使用ANT来对应用打包,一般会经过以下几个步骤:

      1.用aapt命令生成R.java文件

      2.用aidl命令生成相应java文件

      3.用javac命令编译java源文件生成class文件

      4.用dx.bat将class文件转换成classes.dex文件

      5.用aapt命令生成资源包文件resources.ap_

      6.用apkbuilder.bat打包资源和classes.dex文件,生成unsigned.apk

      7.用jarsinger命令对apk认证,生成signed.apk

      为了便于理解和记忆,下面来用一张流程图来说明以上的几个过程:

      以上就是整体的流程,下面我们就对其每个部分进行做出详细讲解,把每一个步骤都弄清楚了。

      我们需要先熟悉一下每一个步骤所使用到的命令:

      1.aapt(Android Asset Packaging Tool)命令,根据资源文件生成R.java文件

      参数说明:

      -f  强制覆盖已存在的文件。
      -m  在-J指定的位置下自动生成相应的包的目录。
      -J  指定R.java文件生成的目录。
      -S  指定资源目录。
      -M  指定清单文件。
      -I  引入类库。

      注意,我们当前所在的位置是ant项目根目录,所以必要时需要输入很多关于命令的路径,以下示例也是一样。

      2.aidl(Android Interface Definition Language)命令,根据.aidl定义文件生成java文件

      上面的示例所在位置为com/scott/ant下,根据包中的Person.aidl文件,在gen对应的目录中生成Person.java文件,示例中只是处理单一文件,下文中会讲述如何处理目录中的多个aidl文件。

      3.javac(Java Compiler)命令,根据源文件生成对应的class文件

      参数说明:

      -d <目录>      指定存放生成的类文件的位置
      -bootclasspath <路径>     覆盖引导类文件的位置

      示例中并没有考虑到引用类路径下面的类库,复杂的情况会在稍后遇到的。

      4.dx命令,将class文件转换成.dex文件

      以上示例是将bin目录下的class文件转换成classes.dex文件,输出到bin目录,我们也许会用到第三方类库,等一会就会看到。

      5.aapt将资源文件打包

      参数说明:

      -f 强制覆盖

      -M 指定Manifest文件

      -S 指定资源目录

      -A 指定资产目录

      -I 指定引入的类库

      -F 指定要生成的包

      6.apkbuilder命令,根据classes.dex文件和resources.ap_生成为签证的apk包

      参数说明:

      -rf 参照源文件的目录的结构

      7.jarsigner命令,对上面生成的apk包进行签证

      在签证的过程中,需要使用到证书文件,需要注意的是最后的release是证书的别名,关于如何创建证书,请看下图:

      当然也可以在eclipse里使用ADT提供的图形界面完成以上步骤,选中项目,点击右键,“Android Tools=>Export Signed Application Package”,然后再其中的Keystore selection环节选择“Create new keystore”,然后按照提示填写信息就可以了。

      以上是我们使用到的命令,接下来我们就该来分析一下ANT所必须的build.xml:

      首先我们需要定义大量的变量属性,用来表示使用到的路径、目录等,如下:

      [html]  view plain copy

      1. <project name="ant" default="release">  

      2.     <!-- ANT环境变量 -->  

      3.     <property environment="env" />  

      4.     <!-- 应用名称 -->  

      5.     <property name="appName" value="${ant.project.name}"/>  

      6.     <!-- SDK目录(获取操作系统环境变量ANDROID_SDK_HOME的值) -->  

      7.     <property name="sdk-folder" value="${env.ANDROID_SDK_HOME}" />  

      8.     <!-- SDK指定平台目录 -->  

      9.     <property name="sdk-platform-folder" value="${sdk-folder}/platforms/android-8"/>  

      10.     <!-- SDK中tools目录 -->  

      11.     <property name="sdk-tools" value="${sdk-folder}/tools" />  

      12.     <!-- SDK指定平台中tools目录 -->  

      13.     <property name="sdk-platform-tools" value="${sdk-platform-folder}/tools" />  

      14.   

      15.     <!-- 使用到的命令(当前系统为windows,如果系统为linux,可将.bat文件替换成相对应的命令) -->  

      16.     <property name="aapt" value="${sdk-platform-tools}/aapt" />  

      17.     <property name="aidl" value="${sdk-platform-tools}/aidl" />  

      18.     <property name="dx" value="${sdk-platform-tools}/dx.bat" />  

      19.     <property name="apkbuilder" value="${sdk-tools}/apkbuilder.bat" />  

      20.     <property name="jarsigner" value="${env.JAVA_HOME}/bin/jarsigner" />  

      21.       

      22.     <!-- 编译需要的jar; 如果项目使用到地图服务则需要maps.jar -->  

      23.     <property name="android-jar" value="${sdk-platform-folder}/android.jar" />  

      24.     <property name="android-maps-jar" value="${sdk-folder}/add-ons/addon_google_apis_google_inc_8/libs/maps.jar"/>  

      25.       

      26.     <!-- 编译aidl文件所需的预处理框架文件framework.aidl -->  

      27.     <property name="framework-aidl" value="${sdk-platform-folder}/framework.aidl" />  

      28.   

      29.     <!-- 生成R文件的相对目录 -->  

      30.     <property name="outdir-gen" value="gen" />  

      31.     <!-- 编译后的文件放置目录 -->  

      32.     <property name="outdir-bin" value="bin" />  

      33.       

      34.     <!-- 清单文件 -->  

      35.     <property name="manifest-xml" value="AndroidManifest.xml" />  

      36.     <!-- 源文件目录 -->  

      37.     <property name="resource-dir" value="res" />  

      38.     <property name="asset-dir" value="assets" />  

      39.     <!-- java源文件目录 -->  

      40.     <property name="srcdir" value="src" />  

      41.     <property name="srcdir-ospath" value="${basedir}/${srcdir}" />  

      42.     <!-- 外部类库所在目录 -->  

      43.     <property name="external-lib" value="lib" />  

      44.     <property name="external-lib-ospath" value="${basedir}/${external-lib}" />  

      45.   

      46.     <!-- 生成class目录 -->  

      47.     <property name="outdir-classes" value="${outdir-bin}" />  

      48.     <property name="outdir-classes-ospath" value="${basedir}/${outdir-classes}" />  

      49.   

      50.     <!-- classes.dex相关变量 -->  

      51.     <property name="dex-file" value="classes.dex" />  

      52.     <property name="dex-path" value="${outdir-bin}/${dex-file}" />  

      53.     <property name="dex-ospath" value="${basedir}/${dex-path}" />  

      54.   

      55.     <!-- 经过aapt生成的资源包文件 -->  

      56.     <property name="resources-package" value="${outdir-bin}/resources.ap_" />  

      57.     <property name="resources-package-ospath" value="${basedir}/${resources-package}" />  

      58.       

      59.     <!-- 未认证apk包 -->  

      60.     <property name="out-unsigned-package" value="${outdir-bin}/${appName}-unsigned.apk" />  

      61.     <property name="out-unsigned-package-ospath" value="${basedir}/${out-unsigned-package}" />  

      62.       

      63.     <!-- 证书文件 -->  

      64.     <property name="keystore-file" value="${basedir}/release.keystore" />  

      65.       

      66.     <!-- 已认证apk包 -->  

      67.     <property name="out-signed-package" value="${outdir-bin}/${appName}.apk" />  

      68.     <property name="out-signed-package-ospath" value="${basedir}/${out-signed-package}" />  

      69.         ...  

      70. </project>  


      然后,我们分步骤来进行,首先是初始化:

      [html]  view plain copy

      1. <!-- 初始化工作 -->  

      2.     <target name="init">  

      3.         <echo>Initializing all output directories...</echo>  

      4.         <delete dir="${outdir-bin}" />  

      5.         <mkdir dir="${outdir-bin}" />  

      6.         <mkdir dir="${outdir-classes}" />  

      7.     </target>  

      其次是生成R.java文件:

      [html]  view plain copy

      1. <!-- 根据工程中的资源文件生成R.java文件  -->  

      2.     <target name="gen-R" depends="init">  

      3.         <echo>Generating R.java from the resources...</echo>  

      4.         <exec executable="${aapt}" failonerror="true">  

      5.             <arg value="package" />  

      6.             <arg value="-f" />  

      7.             <arg value="-m" />  

      8.             <arg value="-J" />  

      9.             <arg value="${outdir-gen}" />  

      10.             <arg value="-S" />  

      11.             <arg value="${resource-dir}" />  

      12.             <arg value="-M" />  

      13.             <arg value="${manifest-xml}" />  

      14.             <arg value="-I" />  

      15.             <arg value="${android-jar}" />  

      16.         </exec>  

      17.     </target>  

      接着是aidl生成java源文件:

      [html]  view plain copy

      1. <!-- 编译aidl文件 -->  

      2.     <target name="aidl" depends="gen-R">  

      3.         <echo>Compiling .aidl into java files...</echo>  

      4.         <apply executable="${aidl}" failonerror="true">  

      5.             <!-- 指定预处理文件 -->  

      6.             <arg value="-p${framework-aidl}"/>  

      7.             <!-- aidl声明的目录 -->  

      8.             <arg value="-I${srcdir}"/>  

      9.             <!-- 目标文件目录 -->  

      10.             <arg value="-o${outdir-gen}"/>  

      11.             <!-- 指定哪些文件需要编译 -->  

      12.             <fileset dir="${srcdir}">  

      13.                 <include name="**/*.aidl"/>  

      14.             </fileset>  

      15.         </apply>  

      16.     </target>  

      我们指定了一个framework.aidl,里面定义了很多android内置对象,然后我们指定了aidl所在目录和输出目录,组后指定编译后缀为aidl的文件。

      接下来是将源文件编译成class文件:

      [html]  view plain copy

      1. <!-- 将工程中的java源文件编译成class文件 -->  

      2.     <target name="compile" depends="aidl">  

      3.         <echo>Compiling java source code...</echo>  

      4.         <javac encoding="utf-8" target="1.5" srcdir="." destdir="${outdir-classes}" bootclasspath="${android-jar}">  

      5.             <classpath>  

      6.                 <fileset dir="${external-lib}" includes="*.jar"/>  

      7.                 <filelist>  

      8.                     <file name="${android-maps-jar}"/>  

      9.                 </filelist>  

      10.             </classpath>  

      11.         </javac>  

      12.     </target>  

      如果使用到了第三方类库,我们可以在classpath标签下配置。

      接着是将class文件转换成classes.dex:

      [html]  view plain copy

      1. <!-- 将.class文件转化成.dex文件 -->  

      2.     <target name="dex" depends="compile">  

      3.         <echo>Converting compiled files and external libraries into a .dex file...</echo>  

      4.         <exec executable="${dx}" failonerror="true">  

      5.             <arg value="--dex" />  

      6.             <!-- 输出文件 -->  

      7.             <arg value="--output=${dex-ospath}" />  

      8.             <!-- 要生成.dex文件的源classes和libraries -->  

      9.             <arg value="${outdir-classes-ospath}" />  

      10.             <arg value="${external-lib-ospath}"/>  

      11.         </exec>  

      12.     </target>  

      就像上面的代码一样,如果使用到第三方类库,可以在最后一参数的形式追加进去。

      然后是将资源文件打包:

      [html]  view plain copy

      1. <!-- 将资源文件放进输出目录 -->  

      2.     <target name="package-res-and-assets">  

      3.         <echo>Packaging resources and assets...</echo>  

      4.         <exec executable="${aapt}" failonerror="true">  

      5.             <arg value="package" />  

      6.             <arg value="-f" />  

      7.             <arg value="-M" />  

      8.             <arg value="${manifest-xml}" />  

      9.             <arg value="-S" />  

      10.             <arg value="${resource-dir}" />  

      11.             <arg value="-A" />  

      12.             <arg value="${asset-dir}" />  

      13.             <arg value="-I" />  

      14.             <arg value="${android-jar}" />  

      15.             <arg value="-F" />  

      16.             <arg value="${resources-package}" />  

      17.         </exec>  

      18.     </target>  

      接着是打包成未签证的apk包:

      [html]  view plain copy

      1. <!-- 打包成未签证的apk -->  

      2.     <target name="package" depends="dex, package-res-and-assets">  

      3.         <echo>Packaging unsigned apk for release...</echo>  

      4.         <exec executable="${apkbuilder}" failonerror="true">  

      5.             <arg value="${out-unsigned-package-ospath}" />  

      6.             <arg value="-u" />  

      7.             <arg value="-z" />  

      8.             <arg value="${resources-package-ospath}" />  

      9.             <arg value="-f" />  

      10.             <arg value="${dex-ospath}" />  

      11.             <arg value="-rf" />  

      12.             <arg value="${srcdir-ospath}" />  

      13.         </exec>  

      14.         <echo>It will need to be signed with jarsigner before being published.</echo>  

      15.     </target>  

      然后是对apk签证:

      [html]  view plain copy

      1. <!-- 对apk进行签证 -->  

      2.     <target name="jarsigner" depends="package">  

      3.         <echo>Packaging signed apk for release...</echo>  

      4.         <exec executable="${jarsigner}" failonerror="true">  

      5.             <arg value="-keystore" />  

      6.             <arg value="${keystore-file}" />  

      7.             <arg value="-storepass" />  

      8.             <arg value="123456" />  

      9.             <arg value="-keypass" />  

      10.             <arg value="123456" />  

      11.             <arg value="-signedjar" />  

      12.             <arg value="${out-signed-package-ospath}" />  

      13.             <arg value="${out-unsigned-package-ospath}"/>  

      14.             <!-- 不要忘了证书的别名 -->  

      15.             <arg value="release"/>  

      16.         </exec>  

      17.     </target>  

      最后发布:

      [html]  view plain copy

      1. <!-- 发布 -->  

      2.     <target name="release" depends="jarsigner">  

      3.         <!-- 删除未签证apk -->  

      4.         <delete file="${out-unsigned-package-ospath}"/>  

      5.         <echo>APK is released. path:${out-signed-package-ospath}</echo>  

      6.     </target>  

      这样就完成了build.xml的编辑,eclipse继承了ANT,所以我们可以在eclipse中直接运行,也可以在代码中调用。

      首先我们需要下载ANT,然后配置相应的环境变量信息,最后我们这样调用:

      [java]  view plain copy

      1. Process p = Runtime.getRuntime().exec("ant.bat -buildfile d:/workspace/ant/build.xml");  

      2. InputStream is = p.getInputStream();  

      3. BufferedReader br = new BufferedReader(new InputStreamReader(is));  

      4. String line = null;  

      5. while ((line = br.readLine()) != null) {  

      6.     System.out.println(line);  

      7. }  

      8. System.out.println("SUCCESS."); 


      发布于 1年前, 阅读(94) | 评论(0) | 投票(0) | 收藏(14) 阅读全文...
    • mac 安装ant具体方法

      分类: Anroid开发
      312014-03

      最近整理了一下ant的下载和安装方法,步骤如下:

      1.下载ant:官网下载

      当前最新版是Apache Ant 1.9.3,可以下载那个zip包,如下图:

      2.将下载的zip包解压到一个目录下,如/usr/local。这时候需要你提供修改权限,输入密码。

      Tip:什么?不会进入usr目录?打开Finder,选择菜单中的“前往”>“前往文件夹”,或者在打开Finder后用快捷键“shift+command+G”,就进入到了/usr/local目录下。

      3.配置环境变量:

      1)获取root权限

      $sudo -s根据提示输入管理员密码,提示符会改成bash-3.2#2)修改bashrc文件读写权限

      bash-3.2#chmod +w /etc/bashrc

      3)查看修改权限后的结果,如显示类似下面,说明修改权限成功。

      -rw-rw-rw-1 rootwheel8161 13 13:55 /etc/bashrc

      4)修改bashrc文件

      bash-3.2#vi /etc/bashrc

      按i键进入编辑状态,在文件末尾加入下面两行

      export ANT_HOME=/usr/local/apache-ant-1.9.3

      export PATH=${PATH}:${ANT_HOME}/bin

      Tip:其中“apache-ant-1.9.3”是你解压缩的文件夹名称

      按ESC键退出编辑状态。输入:wq!保存并退出。

      5)测试

      重新打开终端并输入

      $ant -version

      配置成功则显示如下:

      Apache Ant(TM) version 1.9.3 compiled on December 23 2013


      发布于 1年前, 阅读(1366) | 评论(1) | 投票(0) | 收藏(1) 阅读全文...
    • android中关于文件操作的一些方法

      分类: Anroid开发
      292014-03

      package com.lq.android.common.util;


      import java.io.BufferedInputStream;

      import java.io.BufferedOutputStream;

      import java.io.ByteArrayOutputStream;

      import java.io.File;

      import java.io.FileInputStream;

      import java.io.FileOutputStream;

      import java.io.IOException;

      import java.io.InputStream;

      import java.text.DecimalFormat;

      import java.util.Arrays;

      import java.util.Enumeration;

      import java.util.zip.ZipEntry;

      import java.util.zip.ZipFile;

      import java.util.zip.ZipOutputStream;


      import com.lq.android.common.application.ApplicationData;


      /**

       * 文件操作方法</br>

       * 

       * @作者: 刘倩</br>

       * @时间: 2014年3月29日 上午10:52:45</br>

       * @描述: 全局公用的对文件的操作方法</br>

       */

      public class ToolsFile

      {

      /** 定义buffer的大小 */

      private static int BUFFER_SIZE = 1024 * 8;


      /**

       * 拷贝文件

       * 

       * @param fromF

       *            文件的源路径

       * @param toF

       *            文件的目标路径

       */

      public static void copyFile(File fromF, File toF)

      {

      FileInputStream fileInputStream = null;

      FileOutputStream fileOutputStream = null;

      try

      {

      if (!toF.exists())

      {

      toF.createNewFile();

      }

      fileInputStream = new FileInputStream(fromF);

      fileOutputStream = new FileOutputStream(toF);

      byte[] buffer = new byte[BUFFER_SIZE];

      for (int bytesRead = 0; (bytesRead = fileInputStream.read(buffer,

      0, buffer.length)) != -1;)

      {

      fileOutputStream.write(buffer, 0, bytesRead);

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      } finally

      {

      try

      {

      if (fileInputStream != null)

      {

      fileInputStream.close();

      }

      if (fileOutputStream != null)

      {

      fileOutputStream.close();

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }

      }


      /**

       * 复制一个目录或文件

       * 

       * @param from

       *            需要复制的目录或文件 例如: /home/from

       * @param to

       *            复制到的目录或文件 例如: /home/to

       * @param isCover

       *            是否覆盖

       */

      public static void copy(String from, String to, boolean isCover)

      {

      File fromF = new File(from);

      File toF = new File(to + "/" + fromF.getName());

      copyR(from, toF.getAbsolutePath(), isCover);

      }


      /**

       * 复制目录或文件

       * 

       * @param from

       *            源文件

       * @param to

       *            目标文件

       * @param isCover

       *            是否覆盖

       */

      private static void copyR(String from, String to, boolean isCover)

      {

      File fromF = new File(from);

      if (fromF.isDirectory())

      {

      File toF = new File(to);

      toF.mkdirs();

      File[] files = fromF.listFiles();

      for (File file : files)

      {

      try

      {

      File toTmpF = new File(toF.getAbsolutePath() + "/"

      + file.getName());

      copyR(file.getAbsolutePath(), toTmpF.getAbsolutePath(),

      isCover);

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }

      } else

      {

      File toF = new File(to);

      if (!toF.exists())

      {

      try

      {

      toF.createNewFile();

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      copyFile(fromF, toF);

      } else

      {

      if (isCover)

      {

      try

      {

      toF.createNewFile();

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      copyFile(fromF, toF);

      }

      }

      }

      }


      /**

       * 拷贝assets下的文件

       * 

       * @param assetFilePath

       *            assets的文件路径

       * @param to

       *            拷贝到的路径

       */

      public static void copyAssetFile(String assetFilePath, String to)

      {

      InputStream inputStream = null;

      FileOutputStream fileOutputStream = null;

      try

      {

      inputStream = ApplicationData.globalContext.getAssets().open(

      assetFilePath);

      File toDir = new File(to);

      toDir.mkdirs();

      File toFile = new File(

      toDir.getAbsolutePath()

      + "/"

      + assetFilePath.substring(assetFilePath

      .lastIndexOf("/") + 1));

      fileOutputStream = new FileOutputStream(toFile);

      byte[] buffer = new byte[BUFFER_SIZE];

      for (int bytesRead = 0; (bytesRead = inputStream.read(buffer, 0,

      buffer.length)) != -1;)

      {

      fileOutputStream.write(buffer, 0, bytesRead);

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      } finally

      {

      try

      {

      if (inputStream != null)

      {

      inputStream.close();

      }

      if (fileOutputStream != null)

      {

      fileOutputStream.close();

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }

      }


      /**

       * 解压zip文件

       * 

       * @param srcFileFullName

       *            需要被解压的文件地址(包括路径+文件名) 例如:/home/kx.apk

       * @param targetPath

       *            需要解压到的目录 例如:/home/kx

       * @return  是否已经被解压

       */

      public static boolean unzip(String srcFileFullName, String targetPath)

      {

      try

      {

      ZipFile zipFile = new ZipFile(srcFileFullName);

      Enumeration<? extends ZipEntry> emu = zipFile.entries();

      while (emu.hasMoreElements())

      {

      ZipEntry entry = (ZipEntry) emu.nextElement();

      // 会把目录作为一个file读出一次,所以只建立目录就可以,之下的文件还会被迭代到

      if (entry.isDirectory())

      {

      new File(targetPath + entry.getName()).mkdirs();

      continue;

      }

      BufferedInputStream bis = new BufferedInputStream(

      zipFile.getInputStream(entry));

      File file = new File(targetPath + entry.getName());

      // 加入这个的原因是zipFile读取文件是随机读取的,这就造成可能先读取一个文件,而这个文件所在的目录还没有出现过,所以要建出目录来

      File parent = file.getParentFile();

      if (parent != null && !parent.exists())

      {

      parent.mkdirs();

      }


      FileOutputStream fos = new FileOutputStream(file);

      BufferedOutputStream bos = new BufferedOutputStream(fos,

      BUFFER_SIZE);


      int count;

      byte data[] = new byte[BUFFER_SIZE];

      while ((count = bis.read(data, 0, BUFFER_SIZE)) != -1)

      {

      bos.write(data, 0, count);

      }

      bos.flush();

      bos.close();

      bis.close();

      }

      zipFile.close();

      return true;

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      return false;

      }


      /**

       * 压缩文件或目录

       * 

       * @param srcPath

       *            被压缩的文件或目录地址 例如: /home/kx 或 /home/kx/kx.apk

       * @param targetFileFullName

       *            压缩后的文件地址全程(包括路径+文件名)例如: /home/kx.apk

       */

      public static void zip(String srcPath, String targetFileFullName)

      {

      ZipOutputStream outputStream = null;

      FileOutputStream fileOutputStream = null;

      try

      {

      fileOutputStream = new FileOutputStream(targetFileFullName);

      outputStream = new ZipOutputStream(fileOutputStream);

      zip(outputStream, new File(srcPath), "");

      } catch (Exception e)

      {

      e.printStackTrace();

      } finally

      {

      try

      {

      if (outputStream != null)

      {

      outputStream.close();

      }

      if (fileOutputStream != null)

      {

      fileOutputStream.close();

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }

      }


      /**

       * 压缩文件或目录的具体方法

       * 

       * @param outputStream

       *            压缩的流

       * @param file

       *            文件路径

       * @param string

       */

      private static void zip(ZipOutputStream out, File file, String base)

      {

      if (file.isDirectory())

      {

      File[] fl = file.listFiles();

      base = base.length() == 0 ? "" : base + "/";

      for (int i = 0; i < fl.length; i++)

      {

      zip(out, fl[i], base + fl[i].getName());

      }

      } else

      {

      FileInputStream in = null;

      BufferedInputStream bis = null;

      try

      {

      out.putNextEntry(new ZipEntry(base));

      in = new FileInputStream(file);

      byte[] buffer = new byte[BUFFER_SIZE];

      bis = new BufferedInputStream(in, BUFFER_SIZE);

      int size;

      while ((size = bis.read(buffer)) != -1)

      {

      out.write(buffer, 0, size);

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      } finally

      {

      try

      {

      if (in != null)

      {

      in.close();

      }

      if (bis != null)

      {

      bis.close();

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }

      }

      }


      /**

       * 删除文件

       * 

       * @param filePath

       *            删除的文件路径

       */

      public static void deleteFile(String filePath)

      {

      if (null == filePath || 0 == filePath.length())

      {

      return;

      }

      try

      {

      File file = new File(filePath);

      if (null != file && file.exists())

      {

      if (file.isDirectory())// 判断是否为文件夹

      {

      File[] fileList = file.listFiles();

      for (int i = 0; i < fileList.length; i++)

      {

      String path = fileList[i].getPath();

      deleteFile(path);

      }

      file.delete();

      }

      if (file.isFile())// 判断是否为文件

      {

      file.delete();

      }

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }


      /**

       * 删除目录下的制定文件

       * 

       * @param filePath

       *            文件路径

       * @param type

       *            文件类型

       */

      public static void deleteFileByType(String filePath, String type)

      {

      if (null == filePath || 0 == filePath.length())

      {

      return;

      }

      try

      {

      File file = new File(filePath);

      if (null != file && file.isDirectory())

      {

      File[] fileList = file.listFiles();

      for (int i = 0; i < fileList.length; i++)

      {

      String path = fileList[i].getPath();

      if (null != path && path.endsWith(type))

      {

      File fileDel = new File(path);

      if (null != fileDel && fileDel.exists())

      {

      fileDel.delete();

      }

      }

      }

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      }


      /**

       * dirStr1中是否包含所有dirStr2中的内容

       * 

       * @param dirStr1

       *            文件

       * @param dirStr2

       *            文件

       * @return  是否有包含关系

       */

      public static boolean isContain(String dirStr1, String dirStr2)

      {

      File dir1 = new File(dirStr1);

      File dir2 = new File(dirStr2);

      boolean result = false;

      try

      {

      result = Arrays.asList(dir1.list()).containsAll(

      Arrays.asList(dir2.list()));

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      return result;

      }


      /**

       * InputStream->byte[]方法

       * 

       * @param inputStream

       *            输入流

       * @param wantReadLean

       *            读多少

       * @return  返回字节数组

       * @throws  IOException

       *             流操作中的io异常

       */

      public static final byte[] readBytes(InputStream inputStream,

      int wantReadLean) throws IOException

      {

      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

      byte[] bys = null;

      try

      {

      byte abyte0[] = new byte[1024];

      int readLength;

      for (int totoalLen = 0; (wantReadLean == 0 || wantReadLean > 0

      && wantReadLean > totoalLen)

      && -1 != (readLength = inputStream.read(abyte0));)

      {

      totoalLen += readLength;

      byteArrayOutputStream.write(abyte0, 0, readLength);

      }

      bys = byteArrayOutputStream.toByteArray();

      } catch (Exception e)

      {

      e.printStackTrace();

      } finally

      {

      if (byteArrayOutputStream != null)

      {

      byteArrayOutputStream.close();

      }

      }

      return bys;

      }


      /**

       * 获取文件夹大小

       * 

       * @param file

       *            文件

       * @return  返回文件的大小

       */

      public static long getFileSize(File file)

      {

      if (file == null || !file.exists())

      {

      return 0;

      }

      long size = 0;

      try

      {

      File[] flist = file.listFiles();

      for (int i = 0; i < flist.length; i++)

      {

      if (flist[i].isDirectory())

      {

      size += getFileSize(flist[i]);

      } else

      {

      size += flist[i].length();

      }

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      }

      return size;

      }


      /**

       * 转换文件大小

       * 

       * @param size

       *            文件大小

       * @return  转化后的文件大小

       */

      public static String formatFileSize(long size)

      {

      DecimalFormat df = new DecimalFormat("0.00");

      String fileSize = "";

      if (size <= 0)

      {

      fileSize = "0 KB";

      } else if (size < 1024)

      {

      fileSize = df.format((double) size) + " B";

      } else if (size < 1048576)

      {

      fileSize = df.format((double) size / 1024) + " KB";

      } else if (size < 1073741824)

      {

      fileSize = df.format((double) size / 1048576) + " M";

      } else

      {

      fileSize = df.format((double) size / 1073741824) + " G";

      }

      return fileSize;

      }


      /**

       * 判断某个文件是否存在

       * 

       * @param path

       *            文件路径

       * @param name

       *            文件名称

       * @return  返回该文件是否存在

       */

      public static boolean isFileExist(String path, String name)

      {

      boolean re = false;

      try

      {

      if (null != path)

      {

      if (new File(path + name).exists())

      {

      re = true;

      }

      }

      } catch (Exception e)

      {

      e.printStackTrace();

      return false;

      }

      return re;

      }

      }

    0 0
    原创粉丝点击