用原生VideoView进行全屏播放时的问题

节选自:用原生VideoView进行全屏播放时的问题


import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;

public class MyVideoView extends VideoView {
    public MyVideoView(Context context) {
        super(context);
    }

    public MyVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);

        setMeasuredDimension(width, height);
    }
}

很好用的下拉刷新组件SmartRefreshLayout

节选自:Android智能下拉刷新框架-SmartRefreshLayout


SmartRefreshLayout以打造一个强大,稳定,成熟的下拉刷新框架为目标,并集成各种的炫酷、多样、实用、美观的Header和Footer。 正如名字所说,SmartRefreshLayout是一个“聪明”或者“智能”的下拉刷新布局,由于它的“智能”,它不只是支持所有的View,还支持多层嵌套的视图结构。 它继承自ViewGroup 而不是FrameLayout或LinearLayout,提高了性能。 也吸取了现在流行的各种刷新布局的优点,包括谷歌官方的 SwipeRefreshLayout, 其他第三方的 Ultra-Pull-To-RefreshTwinklingRefreshLayout 。 还集成了各种炫酷的 Header 和 Footer。

【Android】Android 监听apk安装替换卸载广播

节选自:【Android】Android 监听apk安装替换卸载广播


首先是要获取应用的安装状态,通过广播的形式

以下是和应用程序相关的Broadcast Action

ACTION_PACKAGE_ADDED 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
ACTION_PACKAGE_REPLACED 一个新版本的应用安装到设备,替换之前已经存在的版本
ACTION_PACKAGE_CHANGED 一个已存在的应用程序包已经改变,包括包名
ACTION_PACKAGE_REMOVED 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
ACTION_PACKAGE_RESTARTED 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
ACTION_PACKAGE_DATA_CLEARED 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)

Socket通讯工具类

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Socket通讯工具类
 */
public class SocketUtil {

    // 线程池
    private static final ExecutorService ThreadPool = Executors.newCachedThreadPool();

    /**
     * 发送Socket消息
     *
     * @param targetIP   目标IP
     * @param targetPort 目标端口
     * @param msg        消息
     * @param callback   回调
     */
    public static void sendSocketMsg(final String targetIP, final int targetPort, final byte[] msg, final SocketUtilCallback callback) {
        ThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    // 建立Socket连接
                    Socket socket = new Socket(targetIP, targetPort);
                    socket.setSoTimeout(1000 * 10);
                    // 写消息
                    OutputStream out = socket.getOutputStream();
                    out.write(msg);
                    out.flush();
                    // 读取消息返回
                    byte[] readBuffer = new byte[1024];
                    InputStream in = socket.getInputStream();
                    int size = in.read(readBuffer);
                    byte[] readBytes = null;
                    if (size != -1) {
                        readBytes = new byte[size];
                        System.arraycopy(readBuffer, 0, readBytes, 0, size);
                    }
                    // 关闭流和Socket连接
                    in.close();
                    out.close();
                    socket.close();
                    // 执行发送成功回调
                    if (callback != null && readBytes != null) {
                        callback.onSuccess(readBytes);
                    }
                } catch (IOException e) {
                    // 执行发送失败回调
                    if (callback != null) {
                        callback.onError(e);
                    }
                }
            }
        });
    }

    /**
     * 回调
     */
    public interface SocketUtilCallback {
        void onSuccess(byte[] result);

        void onError(Exception e);
    }
}