第一个 Android app 开发经验总结

文章目录

      • 1. Eventbus库
      • 2. 按两下退出activity的实现方法
      • 3. 通过U盘插入广播 U盘路径的方法
        • PS:发送自定义广播的方法:
      • 4. 视频全屏播放的方法
      • 5. 线程和主线程通信 Handler
      • 6. 无需通过U盘插入广播 获取外置SD卡或挂载U盘路径的方法
      • 7. Tcp网络通信实现demo
      • Tips

1. Eventbus库

当模块间互相调用方法的时候,可以使用eventbus库,进行快速调用。

使用方法 参考博客

Github地址

2. 按两下退出activity的实现方法

重写返回键方法

    private static boolean isSysExit = false;
    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        if(!isSysExit){
            isSysExit = true;

            Toast.makeText(this, "按返回键确认退出", Toast.LENGTH_SHORT).show();
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    isSysExit =false;
                }
            }, 2000);
        }else {
            finish();
        }
    }

3. 通过U盘插入广播 U盘路径的方法

使用方法 参考博客

第一步现在xml下静态注册广播接收器(英文高版本不支持原因,推荐动态注册)

 
  
      
          
          
          
          
          
      
  

推荐的静态注册方法 (放在了MainActivity的onCreate方法里)

    // 1. 实例化BroadcastReceiver子类 &  IntentFilter
    USBReceiver mUSBReceiver = new USBReceiver();
    IntentFilter intentFilter = new IntentFilter();
    // 2. 设置接收广播的类型
    intentFilter.addAction("com.example.whitebalance.USBReceiver");
    intentFilter.addAction("android.intent.action.BOOT_COMPLETED");
    intentFilter.addAction("android.intent.action.MEDIA_MOUNTED");
    intentFilter.addAction("android.intent.action.MEDIA_UNMOUNTED");
    intentFilter.addAction("android.intent.action.MEDIA_REMOVED" );
    intentFilter.addDataScheme("file" );
    // 3. 动态注册:调用Context的registerReceiver()方法
    registerReceiver(mUSBReceiver, intentFilter);

新建一个接收器类

 public class USBReceiver extends BroadcastReceiver {
      private static final String TAG = USBReceiver.class.getSimpleName();
      private static final String MOUNTS_FILE = "/proc/mounts";
      private StorageManager mStorageManager;
  
      @Override
      public void onReceive(Context context, Intent intent) {
          mStorageManager = (StorageManager) context.getSystemService(Activity.STORAGE_SERVICE);
          String action = intent.getAction();
          if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
              String mountPath = intent.getData().getPath();
              Uri data = intent.getData();
              Log.d(TAG, "mountPath = " + mountPath);
              if (!TextUtils.isEmpty(mountPath)) {
                  //读取到U盘路径再做其他业务逻辑
                  SPUtils.getInstance().put("UsbPath", mountPath);
                  boolean mounted = isMounted(mountPath);
                  Log.d(TAG, "onReceive: " + "U盘挂载" + mounted);
                  getUName();
              }
          } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) || action.equals(Intent.ACTION_MEDIA_EJECT)) {
              Log.d(TAG, "onReceive: " + "U盘移除了");
          } else if (action.equals("android.intent.action.BOOT_COMPLETED")) {
              //如果是开机完成,则需要调用另外的方法获取U盘的路径
          }
      }
  
  
      /**
       * 判断是否有U盘插入,当U盘开机之前插入使用该方法.
       * @param path
       * @return
       */
      public static boolean isMounted(String path) {
          boolean blnRet = false;
          String strLine = null;
          BufferedReader reader = null;
          try {
              reader = new BufferedReader(new FileReader(MOUNTS_FILE));
  
              while ((strLine = reader.readLine()) != null) {
                  if (strLine.contains(path)) {
                      blnRet = true;
                      break;
                  }
              }
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              if (reader != null) {
                  try {
                      reader.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
                  reader = null;
              }
          }
          return blnRet;
      }
  
  
      /**
       * 获取U盘的路径和名称
       */
      private void getUName() {
          Class volumeInfoClazz = null;
          Method getDescriptionComparator = null;
          Method getBestVolumeDescription = null;
          Method getVolumes = null;
          Method isMountedReadable = null;
          Method getType = null;
          Method getPath = null;
          List volumes = null;
          try {
              volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");
              getDescriptionComparator = volumeInfoClazz.getMethod("getDescriptionComparator");
              getBestVolumeDescription = StorageManager.class.getMethod("getBestVolumeDescription", volumeInfoClazz);
              getVolumes = StorageManager.class.getMethod("getVolumes");
              isMountedReadable = volumeInfoClazz.getMethod("isMountedReadable");
              getType = volumeInfoClazz.getMethod("getType");
              getPath = volumeInfoClazz.getMethod("getPath");
              volumes = (List) getVolumes.invoke(mStorageManager);
  
              for (Object vol : volumes) {
                  if (vol != null && (boolean) isMountedReadable.invoke(vol) && (int) getType.invoke(vol) == 0) {
                      File path2 = (File) getPath.invoke(vol);
                      String p1 = (String) getBestVolumeDescription.invoke(mStorageManager, vol);
                      String p2 = path2.getPath();
                      Log.d(TAG, "-----------path1-----------------" + p1);               //打印U盘卷标名称
                      Log.d(TAG, "-----------path2 @@@@@-----------------" + p2);         //打印U盘路径
                  }
              }
          } catch (Exception ex) {
              ex.printStackTrace();
          }
      }
  }

PS:发送自定义广播的方法:

Intent it = new Intent("com.example.whitebalance.PreUSBReceiver");//自定义的广播名称
sendBroadcast(it);

4. 视频全屏播放的方法

让video组件和父组件大小一致,布局文件


然后设置一个主题样式即可(NoActionBar)

    

5. 线程和主线程通信 Handler

注册

@SuppressLint("HandlerLeak")
    Handler toastHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            switch (msg.what){
                case 1:
                    Toast.makeText(getApplicationContext(), "PC连接成功", Toast.LENGTH_LONG).show();
                    break;
            }
            super.handleMessage(msg);
        }
    };

使用

ConnectPCService.this.toastHandler.sendEmptyMessage(1);

6. 无需通过U盘插入广播 获取外置SD卡或挂载U盘路径的方法

使用方法 参考博客

  1. 在清掉AndroidManifest.xml文件中添加需要的权限
 
 
 
  1. 通过反射获取外置SD卡或挂载U盘路径
  private StorageManager mStorageManager;
  mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
  //获取所有挂载的设备(内部sd卡、外部sd卡、挂载的U盘)
  List volumes = mStorageManager.getStorageVolumes();
  try {
   Class storageVolumeClazz = Class
     .forName("android.os.storage.StorageVolume");
   //通过反射调用系统hide的方法
   Method getPath = storageVolumeClazz.getMethod("getPath");
   Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
   for (int i = 0; i < volumes.size(); i++) {
    StorageVolume storageVolume = volumes.get(i);//获取每个挂载的StorageVolume
    
    //通过反射调用getPath、isRemovable
    String storagePath = (String) getPath.invoke(storageVolume); //获取路径
    boolean isRemovableResult = (boolean) isRemovable.invoke(storageVolume);//是否可移除
    String description = storageVolume.getDescription(this);
    Log.d("jason", " i=" + i + " ,storagePath=" + storagePath
      + " ,isRemovableResult=" + isRemovableResult +" ,description="+description);
   }
  } catch (Exception e) {
   Log.d("jason", " e:" + e);
  }

7. Tcp网络通信实现demo

public class ConnectPCService extends Service {
    private Socket mSocket;
    private SocketConnectThread socketConnectThread;
    private OutputStream mOutStream;
    private InputStream mInStream;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Let it continue running until it is stopped.
        Toast.makeText(this, "服务已经启动", Toast.LENGTH_LONG).show();
        socketConnectThread = new SocketConnectThread(USB_config.PCIP);
        socketConnectThread.start();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "服务已经停止", Toast.LENGTH_LONG).show();
    }

    //service 内部类
    class SocketConnectThread extends Thread{
        private  String IP;
        public SocketConnectThread(String IP){
            this.IP = IP;
        }
        public void run(){
            Log.e("info", "run: ============socket线程启动" );
            try {
                //指定ip地址和端口号
                if(mSocket != null) mSocket.close();
                mSocket = new Socket(this.IP, 1989);
                Log.e("info", "run: "+ this.IP);
                if(mSocket != null){
                    //获取输出流、输入流
                    mOutStream = mSocket.getOutputStream();
                    mInStream = mSocket.getInputStream();
                }else {
                    Log.e("info", "run: =========scoket==null");
                }
                Log.e("info","connect success========================================");
                send(this.IP);
                startReader(mSocket);
            } catch (Exception e) {
                e.printStackTrace();
                if(mSocket != null) {
                    try {
                        mSocket.close();
                    }catch (Exception ee) {
                        ee.printStackTrace();
                    }
                }
                return;
            }
        }
    }
    
    private void startReader(final Socket socket) {
        new Thread(){
            @Override
            public void run() {
                DataInputStream reader;
                try {
                    // 获取读取流
                    reader = new DataInputStream(socket.getInputStream());
                    while (true) {
                        System.out.println("*等待客户端输入*");
                        //Thread.currentThread().sleep(1000);
                        // 读取数据
                        String msg="";
                        Log.d("msg", "Read Attempt");
                        msg = reader.readLine();
                        if (msg == null)
                        {
                            Log.d("msg", "continue");
                            Thread.currentThread().sleep(1000);
                            continue;
                        }
                        Log.d("msg", "获取到客户端的信息:=" + msg);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("msg", "Read Failed  e",e);
                } catch(InterruptedException e)
                {
                    Log.e("msg", "Failed  ee",e);
                }finally {
                    try {
                        Log.e("msg", "Read close");
                        mSocket.close();
                    }catch (Exception ee) {
                        ee.printStackTrace();
                    }
                }

            }
        }.start();

    }

    public void send(final String str) {
        if (str.length() == 0){
            return;
        }
        new Thread() {
            @Override
            public void run() {
                try {
                    // socket.getInputStream()
                    DataOutputStream writer = new DataOutputStream(mSocket.getOutputStream());
                    writer.writeUTF(str); // 写一个UTF-8的信息
                    System.out.println("发送消息");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

Tips

  1. 永远不要用记事本来写代码,可以用NotePad 、Sublime、 VS Code等

你可能感兴趣的:(经验总结,android,java)