Android自定义拍照实现

节选自:Android自定义拍照实现


/**
 * 注释:拍照并保存图片到相册
 * 时间:2019/3/1 0001 15:37
 * 作者:郭翰林
 */
private void takePhoto() {
    isTakePhoto = true;
    //调用相机拍照
    mCamera.takePicture(null, null, null, (data, camera1) -> {
        //视图动画
        mPhotoLayout.setVisibility(View.GONE);
        mConfirmLayout.setVisibility(View.VISIBLE);
        AnimSpring.getInstance(mConfirmLayout).startRotateAnim(120, 360);
        imageData = data;
        //停止预览
        mCamera.stopPreview();
    });
}

使用TextView替代Button,使用ImageView替代ImageButton

Button继承自TextView,ImageButton继承自ImageView。

<TextView
    android:id="@+id/nextBtn"
    android:layout_width="250dp"
    android:layout_height="80dp"
    android:background="@drawable/bg_0062ec_40"
    android:gravity="center"
    android:text="下一步"
    android:textColor="#FFFFFF"
    android:textSize="34sp" />
<ImageView
    android:id="@+id/backBtn"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:scaleType="center"
    app:srcCompat="@drawable/icon_back" />

【转】Android中TextView与Button的区别

转载自:Android中TextView与Button的区别


Button继承于TextView,一般情况下,TextView用来承载静态文本,Button用来响应点击事件。但是TextView 继承自View,点击事件是从View就有的特性,所以TextView也能点击。那么TextView与Button有什么不同呢?

1.TextView中文字默认是从左上方开始,Button中文字默认是居中显示

2.TextView默认背景透明,Button默认背景灰色的

3.TextView点击无效果,Button默认状态下点击变黄色(它有一个默认的背景选择器)

4.TextView默认不拦截点击事件,Button会拦截点击事件(比如说我们一个ListView,Item的布局中有一个TextView和Button,我们在这个TextView上点击会触发ListView的OnItemClickListener方法,在Button上点击并不会触发ListView的OnItemClickListener方法,因为Button把这个点击事件拦截了)。

Android Context完全解析

节选自:Android Context完全解析,你所不知道的Context的各种细节


Context一共有三种类型,分别是Application、Activity和Service。

Context数量 = Activity数量 + Service数量 + 1

上面的1代表着Application的数量,因为一个应用程序中可以有多个Activity和多个Service,但是只能有一个Application。

Application单例模式:

public class MyApplication extends Application {

    private static MyApplication app;

    public static MyApplication getInstance() {
        return app;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        app = this;
    }
}

gRPC请求中对header进行处理

节选自:gRPC请求中对header进行处理


1.[Android (Java)]

1.1只设置客户端请求时附带的header

见类 io.grpc.stub.MetadataUtils,其中有个方法:

/**
 * Attaches a set of request headers to a stub.
 *
 * @param stub to bind the headers to.
 * @param extraHeaders the headers to be passed by each call on the returned stub.
 * @return an implementation of the stub with {@code extraHeaders} bound to each call.
 */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1789")
public static <T extends AbstractStub<T>> T attachHeaders(
        T stub,
        final Metadata extraHeaders) {
    return stub.withInterceptors(newAttachHeadersInterceptor(extraHeaders));
}

稍微自己封装一下的效果,如下:

private static <T extends AbstractStub<T>> T attachHeaders(T stub, final Map<String, String> headerMap) {
    Metadata extraHeaders = new Metadata();
    if (headerMap != null) {
        for (String key : headerMap.keySet()) {
            Metadata.Key<String> customHeadKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER);
            extraHeaders.put(customHeadKey, headerMap.get(key));
        }
    }
    return MetadataUtils.attachHeaders(stub, extraHeaders);
}

使Glide支持https

添加依赖

// Glide
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.11.0'

然后就可以了,添加 OkHttp 集成库的 Gradle 依赖将使 Glide 自动开始使用 OkHttp 来加载所有来自 http 和 https URL 的图片。


参考链接:

关于集成库

OkHttp3

关于Glide配置https图片不显示的问题

Glide3.8升级到Glide4.0.0

在Android上使用gRPC

1.Hello

syntax = "proto3";

option java_multiple_files = true;

package hello;

service Hello {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

2.gRPCService

import hello.HelloGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class gRPCService {
    private static final String gRPC_HOST = "isilent.me";
    private static final int gRPC_PORT = 80;
    private static gRPCService instance;
    private ManagedChannel mChannel;

    public static gRPCService getInstance() {
        if (instance == null) {
            instance = new gRPCService();
        }
        return instance;
    }

    private gRPCService() {

    }

    /**
     * 获取Channel
     *
     * @return
     */
    private ManagedChannel getChannel() {
        if (mChannel == null || mChannel.isShutdown()) {
            // 设置最大接收消息大小为20M
            mChannel = ManagedChannelBuilder.forAddress(gRPC_HOST, gRPC_PORT).usePlaintext().maxInboundMessageSize(20 * 1024 * 1024).build();
        }
        return mChannel;
    }

    /**
     * 获取Hello存根
     *
     * @return
     */
    public HelloGrpc.HelloStub getHelloStub() {
        return HelloGrpc.newStub(getChannel());
    }
}

3.SimpleStreamObserver

import android.os.Handler;
import android.os.Looper;

import io.grpc.stub.StreamObserver;

public abstract class SimpleStreamObserver<T> implements StreamObserver<T> {
    private static Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void onCompleted() {

    }

    @Override
    public void onNext(final T value) {
        // 返回主线程
        handler.post(new Runnable() {
            @Override
            public void run() {
                onSuccess(value);
            }
        });
    }

    /**
     * 请求成功的回调
     *
     * @param value
     */
    protected abstract void onSuccess(T value);
}

4.Main

public static void Main() {
    HelloRequest request = HelloRequest.newBuilder().setName("hello").build();
    gRPCService.getInstance().getHelloStub().sayHello(request, new SimpleStreamObserver<HelloReply>() {
        @Override
        protected void onSuccess(HelloReply value) {
            System.out.println(value.getMessage());
        }

        @Override
        public void onError(Throwable t) {

        }
    });
}