文章目录
1. Eventbus库
当模块间互相调用方法的时候,可以使用eventbus库,进行快速调用。
使用方法 参考博客
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下静态注册广播接收器(英文高版本不支持原因,推荐动态注册)
<!-- 监听U盘插拔的广播-->
<receiver android:name=".service.USBReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED" />
<action android:name="android.intent.action.MEDIA_REMOVED"/>
<data android:scheme="file"></data>
</intent-filter>
</receiver>
推荐的静态注册方法 (放在了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组件和父组件大小一致,布局文件
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
然后设置一个主题样式即可(NoActionBar)
<style name="PlayerTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
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盘路径的方法
使用方法 参考博客
- 在清掉AndroidManifest.xml文件中添加需要的权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- 通过反射获取外置SD卡或挂载U盘路径
private StorageManager mStorageManager;
mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
//获取所有挂载的设备(内部sd卡、外部sd卡、挂载的U盘)
List<StorageVolume> 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
- 永远不要用记事本来写代码,可以用NotePad 、Sublime、 VS Code等