本机Android(Java)中的Agora.io

本机Android(Java)中的Agora.io,java,android,agora.io,Java,Android,Agora.io,我知道以前有人问过这个问题,但代码后面提到的查询并没有解决这个问题 package io.agora.tutorials1v1vcall; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support

我知道以前有人问过这个问题,但代码后面提到的查询并没有解决这个问题

package io.agora.tutorials1v1vcall;

    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.support.annotation.NonNull;

    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.SurfaceView;
    import android.view.View;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.Toast;

    import io.agora.uikit.logger.LoggerRecyclerView;
    import io.agora.rtc.IRtcEngineEventHandler;
    import io.agora.rtc.RtcEngine;
    import io.agora.rtc.video.VideoCanvas;
    import io.agora.rtc.video.VideoEncoderConfiguration;

    public class VideoChatViewActivity extends AppCompatActivity {
        private static final String TAG = VideoChatViewActivity.class.getSimpleName();

        private static final int PERMISSION_REQ_ID = 22;

        // Permission WRITE_EXTERNAL_STORAGE is not mandatory
        // for Agora RTC SDK, just in case if you wanna save
        // logs to external sdcard.
        private static final String[] REQUESTED_PERMISSIONS = {
                Manifest.permission.RECORD_AUDIO,
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        private RtcEngine mRtcEngine;
        private boolean mCallEnd;
        private boolean mMuted;

        private FrameLayout mLocalContainer;
        private RelativeLayout mRemoteContainer;
        private SurfaceView mLocalView;
        private SurfaceView mRemoteView;

        private ImageView mCallBtn;
        private ImageView mMuteBtn;
        private ImageView mSwitchCameraBtn;

        // Customized logger view
        private LoggerRecyclerView mLogView;

        /**
         * Event handler registered into RTC engine for RTC callbacks.
         * Note that UI operations needs to be in UI thread because RTC
         * engine deals with the events in a separate thread.
         */
        private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
            @Override
            public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mLogView.logI("Join channel success, uid: " + (uid & 0xFFFFFFFFL));
                    }
                });
            }

            @Override
            public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mLogView.logI("First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
                        setupRemoteVideo(uid);
                    }
                });
            }

            @Override
            public void onUserOffline(final int uid, int reason) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mLogView.logI("User offline, uid: " + (uid & 0xFFFFFFFFL));
                        onRemoteUserLeft();
                    }
                });
            }
        };

        private void setupRemoteVideo(int uid) {
            // Only one remote video view is available for this
            // tutorial. Here we check if there exists a surface
            // view tagged as this uid.
            int count = mRemoteContainer.getChildCount();
            View view = null;
            for (int i = 0; i < count; i++) {
                View v = mRemoteContainer.getChildAt(i);
                if (v.getTag() instanceof Integer && ((int) v.getTag()) == uid) {
                    view = v;
                }
            }

            if (view != null) {
                return;
            }

            mRemoteView = RtcEngine.CreateRendererView(getBaseContext());
            mRemoteContainer.addView(mRemoteView);
            mRtcEngine.setupRemoteVideo(new VideoCanvas(mRemoteView, VideoCanvas.RENDER_MODE_HIDDEN, uid));
            mRemoteView.setTag(uid);
        }

        private void onRemoteUserLeft() {
            removeRemoteVideo();
        }

        private void removeRemoteVideo() {
            if (mRemoteView != null) {
                mRemoteContainer.removeView(mRemoteView);
            }
            mRemoteView = null;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_video_chat_view);
            initUI();

            // Ask for permissions at runtime.
            // This is just an example set of permissions. Other permissions
            // may be needed, and please refer to our online documents.
            if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
                    checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID) &&
                    checkSelfPermission(REQUESTED_PERMISSIONS[2], PERMISSION_REQ_ID)) {
                initEngineAndJoinChannel();
            }
        }

        private void initUI() {
            mLocalContainer = findViewById(R.id.local_video_view_container);
            mRemoteContainer = findViewById(R.id.remote_video_view_container);

            mCallBtn = findViewById(R.id.btn_call);
            mMuteBtn = findViewById(R.id.btn_mute);
            mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);

            mLogView = findViewById(R.id.log_recycler_view);

            // Sample logs are optional.
            showSampleLogs();
        }

        private void showSampleLogs() {
            mLogView.logI("Welcome to Agora 1v1 video call");
            mLogView.logW("You will see custom logs here");
            mLogView.logE("You can also use this to show errors");
        }

        private boolean checkSelfPermission(String permission, int requestCode) {
            if (ContextCompat.checkSelfPermission(this, permission) !=
                    PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
                return false;
            }

            return true;
        }

        @Override
        public void onRequestPermissionsResult(int requestCode,
                                               @NonNull String[] permissions, @NonNull int[] grantResults) {

            if (requestCode == PERMISSION_REQ_ID) {
                if (grantResults[0] != PackageManager.PERMISSION_GRANTED ||
                        grantResults[1] != PackageManager.PERMISSION_GRANTED ||
                        grantResults[2] != PackageManager.PERMISSION_GRANTED) {
                    showLongToast("Need permissions " + Manifest.permission.RECORD_AUDIO +
                            "/" + Manifest.permission.CAMERA + "/" + Manifest.permission.WRITE_EXTERNAL_STORAGE);
                    finish();
                    return;
                }

                // Here we continue only if all permissions are granted.
                // The permissions can also be granted in the system settings manually.
                initEngineAndJoinChannel();
            }
        }

        private void showLongToast(final String msg) {
            this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                }
            });
        }

        private void initEngineAndJoinChannel() {
            // This is our usual steps for joining
            // a channel and starting a call.
            initializeEngine();
            setupVideoConfig();
            setupLocalVideo();
            joinChannel();
        }

        private void initializeEngine() {
            try {
                mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
            } catch (Exception e) {
                Log.e(TAG, Log.getStackTraceString(e));
                throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
            }
        }

        private void setupVideoConfig() {
            // In simple use cases, we only need to enable video capturing
            // and rendering once at the initialization step.
            // Note: audio recording and playing is enabled by default.
            mRtcEngine.enableVideo();

            // Please go to this page for detailed explanation
            // https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#af5f4de754e2c1f493096641c5c5c1d8f
            mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
                    VideoEncoderConfiguration.VD_640x360,
                    VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
                    VideoEncoderConfiguration.STANDARD_BITRATE,
                    VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
        }

        private void setupLocalVideo() {
            // This is used to set a local preview.
            // The steps setting local and remote view are very similar.
            // But note that if the local user do not have a uid or do
            // not care what the uid is, he can set his uid as ZERO.
            // Our server will assign one and return the uid via the event
            // handler callback function (onJoinChannelSuccess) after
            // joining the channel successfully.
            mLocalView = RtcEngine.CreateRendererView(getBaseContext());
            mLocalView.setZOrderMediaOverlay(true);
            mLocalContainer.addView(mLocalView);
            mRtcEngine.setupLocalVideo(new VideoCanvas(mLocalView, VideoCanvas.RENDER_MODE_HIDDEN, 0));
        }

        private void joinChannel() {
            // 1. Users can only see each other after they join the
            // same channel successfully using the same app id.
            // 2. One token is only valid for the channel name that
            // you use to generate this token.
            String token = getString(R.string.agora_access_token);
            if (TextUtils.isEmpty(token) || TextUtils.equals(token, "#YOUR ACCESS TOKEN#")) {
                token = null; // default, no token
            }
            mRtcEngine.joinChannel(token, "demoChannel1", "Extra Optional Data", 0);
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (!mCallEnd) {
                leaveChannel();
            }
            RtcEngine.destroy();
        }

        private void leaveChannel() {
            mRtcEngine.leaveChannel();
        }

        public void onLocalAudioMuteClicked(View view) {
            mMuted = !mMuted;
            mRtcEngine.muteLocalAudioStream(mMuted);
            int res = mMuted ? R.drawable.btn_mute : R.drawable.btn_unmute;
            mMuteBtn.setImageResource(res);
        }

        public void onSwitchCameraClicked(View view) {
            mRtcEngine.switchCamera();
        }

        public void onCallClicked(View view) {
            if (mCallEnd) {
                startCall();
                mCallEnd = false;
                mCallBtn.setImageResource(R.drawable.btn_endcall);
            } else {
                endCall();
                mCallEnd = true;
                mCallBtn.setImageResource(R.drawable.btn_startcall);
            }

            showButtons(!mCallEnd);
        }

        private void startCall() {
            setupLocalVideo();
            joinChannel();
        }

        private void endCall() {
            removeLocalVideo();
            removeRemoteVideo();
            leaveChannel();
        }

        private void removeLocalVideo() {
            if (mLocalView != null) {
                mLocalContainer.removeView(mLocalView);
            }
            mLocalView = null;
        }

        private void showButtons(boolean show) {
            int visibility = show ? View.VISIBLE : View.GONE;
            mMuteBtn.setVisibility(visibility);
            mSwitchCameraBtn.setVisibility(visibility);
        }
    }
包io.agora.tutorials1vCall;
导入android.Manifest;
导入android.content.pm.PackageManager;
导入android.os.Bundle;
导入android.support.annotation.NonNull;
导入android.support.v4.app.ActivityCompat;
导入android.support.v4.content.ContextCompat;
导入android.support.v7.app.AppActivity;
导入android.text.TextUtils;
导入android.util.Log;
导入android.view.SurfaceView;
导入android.view.view;
导入android.widget.FrameLayout;
导入android.widget.ImageView;
导入android.widget.RelativeLayout;
导入android.widget.Toast;
导入io.agora.uikit.logger.LoggerRecyclerView;
导入io.agora.rtc.IRTCEngineeEventHandler;
导入io.agora.rtc.rtcnengine;
导入io.agora.rtc.video.VideoCanvas;
导入io.agora.rtc.video.video编码器配置;
公共类VideoChatViewActivity扩展了AppCompatActivity{
私有静态最终字符串标记=VideoChatViewActivity.class.getSimpleName();
私有静态最终int权限需求ID=22;
//写入外部存储的权限不是强制性的
//对于Agora RTC SDK,以防您想要保存
//记录到外部SD卡。
私有静态最终字符串[]请求的\u权限={
Manifest.permission.RECORD_音频,
舱单,许可,摄像机,
Manifest.permission.WRITE\u外部存储
};
专用RTC引擎mRtcEngine;
私有布尔mCallEnd;
私有布尔运算;
专用框架布局局部容器;
私有相对物mRemoteContainer;
私人SurfaceView mLocalView;
私人SurfaceView mRemoteView;
私有ImageView mCallBtn;
私有图像视图mMuteBtn;
私有ImageView mSwitchCameraBtn;
//自定义记录器视图
私人LoggerRecyclerView mLogView;
/**
*为RTC回调注册到RTC引擎的事件处理程序。
*注意,UI操作需要在UI线程中,因为RTC
*引擎在单独的线程中处理事件。
*/
私有最终IRtcEngineEventHandler mRtcEventHandler=新IRtcEngineEventHandler(){
@凌驾
public void onJoinChannelSuccess(字符串通道、最终整数uid、整数已过){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
logI(“加入频道成功,uid:+(uid&0xffffffffffl));
}
});
}
@凌驾
已解码公共无效onFirstRemoteVideoDecoded(最终整数uid、整数宽度、整数高度、整数经过时间){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
logI(“解码的第一个远程视频,uid:+(uid&0xffffffffffl));
设置远程视频(uid);
}
});
}
@凌驾
公共无效onUserOffline(最终输入uid,输入原因){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
logI(“用户脱机,uid:+(uid&0xffffffffffl));
onRemoteUserLeft();
}
});
}
};
私有void setupRemoteVideo(int-uid){
//只有一个远程视频视图可用于此操作
//教程。这里我们检查是否存在曲面
//标记为此uid的视图。
int count=mRemoteContainer.getChildCount();
视图=空;
for(int i=0;i