From: xiewei <892331662@qq.com> Date: Fri, 12 Jul 2024 09:17:46 +0000 (+0800) Subject: 240712:首次提交 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=5c974e005db3b34083ddd1495c5f7bf4fc8d570c;p=mirrors%2Fpoly-sdk.git 240712:首次提交 --- 5c974e005db3b34083ddd1495c5f7bf4fc8d570c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..71fcb69 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/20240607_092332_2_20240607_110430_ota.fwpkg b/20240607_092332_2_20240607_110430_ota.fwpkg new file mode 100644 index 0000000..b69ae17 Binary files /dev/null and b/20240607_092332_2_20240607_110430_ota.fwpkg differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..116c041 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,49 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.zhixun.android.sdk.polymerizesdk' + compileSdk 33 + + defaultConfig { + applicationId "com.zhixun.android.sdk.polymerizesdk" + minSdk 24 + targetSdk 33 + versionCode 1 + versionName "1.1" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.8.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' +// implementation files('libs\\Poly-SDK-v1.2-24062709.jar') + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + implementation project(path: ':polysdk') +// implementation(fileTree("libs/Poly-SDK-1.3-202407061157.aar")) + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.google.code.gson:gson:2.10' + implementation 'com.github.bumptech.glide:glide:4.0.0-RC1' + +// implementation "org.java-websocket:Java-WebSocket:1.5.1" + implementation 'com.arthenica:mobile-ffmpeg-full:4.4' +// implementation 'com.squareup.okhttp3:okhttp:4.9.1' +} \ No newline at end of file diff --git a/app/libs/Poly-SDK-1.3-202407061153.aar b/app/libs/Poly-SDK-1.3-202407061153.aar new file mode 100644 index 0000000..e435ce3 Binary files /dev/null and b/app/libs/Poly-SDK-1.3-202407061153.aar differ diff --git a/app/libs/Poly-SDK-1.3-202407061157.aar b/app/libs/Poly-SDK-1.3-202407061157.aar new file mode 100644 index 0000000..916db74 Binary files /dev/null and b/app/libs/Poly-SDK-1.3-202407061157.aar differ diff --git a/app/libs/Poly-SDK-v1.2-24062709.jar b/app/libs/Poly-SDK-v1.2-24062709.jar new file mode 100644 index 0000000..de3a7f9 Binary files /dev/null and b/app/libs/Poly-SDK-v1.2-24062709.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/zhixun/android/sdk/polymerizesdk/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/zhixun/android/sdk/polymerizesdk/ExampleInstrumentedTest.java new file mode 100644 index 0000000..8312d9c --- /dev/null +++ b/app/src/androidTest/java/com/zhixun/android/sdk/polymerizesdk/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.zhixun.android.sdk.polymerizesdk", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d5e6d7e --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AigcActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AigcActivity.java new file mode 100644 index 0000000..2891faa --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AigcActivity.java @@ -0,0 +1,176 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Base64; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.bumptech.glide.Glide; +import com.google.gson.Gson; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.callback.AIRequestCallback; +import com.zhixun.android.sdk.polysdk.entity.AigcStyle; +import com.zhixun.android.sdk.polysdk.entity.AigcTask; +import com.zhixun.android.sdk.polysdk.entity.AigcTaskResult; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class AigcActivity extends AppCompatActivity { + + private String TAG = "AigcActivity"; + private ImageView back_img; + private TextView tv_task_state; + private EditText ed_content; + private boolean isTaskRun = false; + private final int MSG_QUERY_TASK = 101; + private final int MSG_QUERY_SUCCESS = 102; + private Handler aigcHandler = new Handler() { + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case MSG_QUERY_TASK: + isTaskRun = true; + tv_task_state.setText("任务状态:进行中"); + queryTask(); + break; + case MSG_QUERY_SUCCESS: + tv_task_state.setText("任务状态:已完成"); + String base64String = (String) msg.obj; + if (!TextUtils.isEmpty(base64String)) { + + // 解码Base64字符串 + byte[] decodedBytes = Base64.decode(base64String.split(",")[1], Base64.DEFAULT); + + // 将字节数组转换为Bitmap + Bitmap bitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length); + + // 设置ImageView的Bitmap + back_img.setImageBitmap(bitmap); + } + break; + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_aigc); + back_img = findViewById(R.id.back_img); + tv_task_state = findViewById(R.id.tv_task_state); + ed_content = findViewById(R.id.ed_content); + } + + public void back(View view) { + finish(); + } + + public void getAigcStyle(View view) { + PolymerizeAgent.getInstance().getAiAPI().getAigcModeList(0, new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + + Log.i(TAG, "getAigcTypeList--" + new Gson().toJson(result)); + } + + @Override + public void onFail(String msg) { + Log.i(TAG, "getAigcTypeList-onFail-" + msg); + } + }); + } + + private String taskId; + + public void creatTask(View view) { + if (isTaskRun) { + Toast.makeText(this, "有任务正在进行,请稍后", Toast.LENGTH_SHORT).show(); + return; + } + String sub = ed_content.getText().toString().trim(); + if (TextUtils.isEmpty(sub)) { + Toast.makeText(this, "请输入你需要的图片描述", Toast.LENGTH_SHORT).show(); + return; + } + AigcTask aigcTask = new AigcTask(); + aigcTask.setType(0); + aigcTask.setAlgorithm("anime"); + aigcTask.setHeight(1024); + aigcTask.setWidth(1024); + aigcTask.setSubject(sub); + PolymerizeAgent.getInstance().getAiAPI().creatAigcImg(aigcTask, new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + Log.i(TAG, "creatTask--" + new Gson().toJson(result)); + taskId = (String) result; + aigcHandler.sendEmptyMessageDelayed(MSG_QUERY_TASK, 1000); + } + + @Override + public void onFail(String msg) { + Log.i(TAG, "creatTask-onFail-" + msg); + } + }); + } + + public void queryTask() { + if (TextUtils.isEmpty(taskId)) return; + Log.i(TAG, "queryTask--" + taskId); + PolymerizeAgent.getInstance().getAiAPI().queryTaskState(taskId, new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + AigcTaskResult taskResult = (AigcTaskResult) result; + Log.i(TAG, "queryTaskState--" + new Gson().toJson(result)); + + if (taskResult.getStatus().equals("RUNNING")||taskResult.getStatus().equals("PENDING")) { + aigcHandler.removeMessages(MSG_QUERY_TASK); + aigcHandler.sendEmptyMessageDelayed(MSG_QUERY_TASK, 1000); + + } else if (taskResult.getStatus().equals("SUCCEEDED")) { + isTaskRun = false; + String imgBase64 = taskResult.getResult(); + if (TextUtils.isEmpty(imgBase64)) return; + Message message = new Message(); + message.what = MSG_QUERY_SUCCESS; + message.obj = imgBase64; + aigcHandler.sendMessage(message); + } else { + runOnUiThread(new Runnable() { + @Override + public void run() { + isTaskRun = false; + tv_task_state.setText("任务状态:失败"); + + } + }); + } + + + } + + @Override + public void onFail(String msg) { + tv_task_state.setText("任务状态:失败"); + Log.i(TAG, "queryTaskState-onFail-" + msg); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/App.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/App.java new file mode 100644 index 0000000..fc88d73 --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/App.java @@ -0,0 +1,14 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import android.app.Application; + +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; + +public class App extends Application { + + @Override + public void onCreate() { + super.onCreate(); + PolymerizeAgent.getInstance().init(this,true,true); + } +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AsrActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AsrActivity.java new file mode 100644 index 0000000..84501f8 --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AsrActivity.java @@ -0,0 +1,181 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; + +import com.zhixun.android.sdk.polymerizesdk.adapter.MsgAdapter; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.callback.AIRequestCallback; +import com.zhixun.android.sdk.polysdk.callback.OnTTSDataChange; +import com.zhixun.android.sdk.polysdk.callback.OnTranscriptionDataChange; + +import java.util.ArrayList; + +public class AsrActivity extends AppCompatActivity { + + private String TAG = "AsrActivity"; + private Button btn_transcrip; + private RecyclerView msg_listview,msg_listview2; + private MsgAdapter msgAdapter,msgAdapter2; + + private boolean isStartTranscrip = false; + + private int msgPosition = -1,msgPosition2 = -1;; + private StringBuffer speedSb = new StringBuffer(); + private StringBuffer speedSb2 = new StringBuffer(); + private MyMediaPlayer mediaPlayer; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_asr); + btn_transcrip = findViewById(R.id.btn_transcrip); + msg_listview = findViewById(R.id.msg_listview); + msgAdapter = new MsgAdapter(this,new ArrayList<>()); + msg_listview.setAdapter(msgAdapter); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + msg_listview.setLayoutManager(layoutManager); + + msg_listview2 = findViewById(R.id.msg_listview2); + msgAdapter2 = new MsgAdapter(this,new ArrayList<>()); + msg_listview2.setAdapter(msgAdapter2); + LinearLayoutManager layoutManager2 = new LinearLayoutManager(this); + msg_listview2.setLayoutManager(layoutManager2); + mediaPlayer = new MyMediaPlayer(); + +// PolymerizeAgent.getInstance().getAiAPI().startSynthesis(); + + PolymerizeAgent.getInstance().getAiAPI().startTrans(); + btn_transcrip.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + msgPosition = -1; + msgPosition2 = -1; + speedSb = new StringBuffer(); + speedSb2 = new StringBuffer(); + isStartTranscrip = true; + AudioRecorderMan.getInstance().startRecording(AsrActivity.this); + return false; + } + }); + btn_transcrip.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()){ + case MotionEvent.ACTION_UP: + if(isStartTranscrip){ +// isStartTranscrip = false; + AudioRecorderMan.getInstance().stopRecording(); + PolymerizeAgent.getInstance().getAiAPI().stopTrans(); + + } + break; + } + return false; + } + }); + + AudioRecorderMan.getInstance().setOnBuffChange(new AudioRecorderMan.onBuffChange() { + @Override + public void onChange(byte[] data) { + Log.i(TAG,"Audio-onChange-"+isStartTranscrip); + if(isStartTranscrip){ + Log.i(TAG,"Audio-onChange-"+data.length); + PolymerizeAgent.getInstance().getAiAPI().sendTransByte(data); + } + } + }); + + PolymerizeAgent.getInstance().getAiAPI().setOnTranscriptionDataChange(new OnTranscriptionDataChange() { + @Override + public void onStartChange(boolean state) { + + } + + @Override + public void onChange(String state,String msg) { + if(state.equals("end")){ + speedSb.append(msg); + translate(msg); + Log.i(TAG,"onChange--"+msg); + runOnUiThread(new Runnable() { + @Override + public void run() { + if(msgPosition==-1){ + msgPosition = msgAdapter.addData(speedSb.toString()); + }else { + msgAdapter.setData(msgPosition,speedSb.toString()); + } + msgAdapter.notifyItemChanged(msgPosition); + + + } + }); + } + + + } + }); + + PolymerizeAgent.getInstance().getAiAPI().setOnTTSDataChange(new OnTTSDataChange() { + @Override + public void onSynthesisChange(byte[] msg) { + Log.e(TAG,"setOnTTSDataChange--"+msg.length); + mediaPlayer.playData(msg); + } + + @Override + public void onLongTextStreamChange(byte[] msg) { + mediaPlayer.playData(msg); + } + }); + } + + private void translate(String msg){ + PolymerizeAgent.getInstance().getAiAPI().translate("en", msg, new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + String text = (String) result; + speedSb2.append(text); + PolymerizeAgent.getInstance().getAiAPI().sendLongTextStream(text); + Log.i(TAG,"translate--"+text); + runOnUiThread(new Runnable() { + @Override + public void run() { + if(msgPosition2==-1){ + msgPosition2 = msgAdapter2.addData(speedSb2.toString()); + }else { + msgAdapter2.setData(msgPosition2,speedSb2.toString()); + } + msgAdapter2.notifyItemChanged(msgPosition2); + + + } + }); + } + + @Override + public void onFail(String msg) { + + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + PolymerizeAgent.getInstance().getAiAPI().stopTrans(); + PolymerizeAgent.getInstance().getAiAPI().stopSynthesis(); + mediaPlayer.stop(); + } + + public void back(View view){ + finish(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java new file mode 100644 index 0000000..927411d --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioPlayer.java @@ -0,0 +1,124 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +public class AudioPlayer { + private AudioTrack audioTrack; + private int bufferSize; + private final int MSG_PLAY = 101; + private String TAG = "AudioPlayer"; + private List playList = new ArrayList<>(); + private Handler audioHandler = new Handler(){ + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + switch (msg.what){ + case MSG_PLAY: + + break; + } + } + }; + public AudioPlayer(int sampleRate, int channelConfig, int audioFormat) { + + // 初始化buffer size + bufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat); + // 初始化AudioTrack + audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, + sampleRate, channelConfig, audioFormat, bufferSize, AudioTrack.MODE_STREAM); + } + + public AudioPlayer() { + int sampleRate = 16000; + int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; + int audioFormat = AudioFormat.ENCODING_PCM_16BIT; + // 初始化buffer size + bufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat); + // 初始化AudioTrack + audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, + sampleRate, channelConfig, audioFormat, bufferSize, AudioTrack.MODE_STREAM); + audioTrack.setPositionNotificationPeriod(bufferSize); + audioTrack.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { + @Override + public void onMarkerReached(AudioTrack track) { + //播放完成 + Log.i(TAG,"onMarkerReached"); + if(playList.size()>0){ + play(playList.get(0)); + playList.remove(0); + } + } + + @Override + public void onPeriodicNotification(AudioTrack track) { + + } + }); + } + + + public void play(byte[] audioData) { + if (audioTrack != null) { + + int state = audioTrack.getPlaybackHeadPosition(); + Log.e(TAG,"paly state="+state); + if (state > 0) { + // AudioTrack正在播放或暂停 + playList.add(audioData); + }else { + new Thread(new Runnable() { + @Override + public void run() { + // 写入数据并播放 + audioTrack.write(audioData, 0, audioData.length); + // 播放音频 + audioTrack.play(); + double audioDurationInSeconds = (double) audioData.length / (audioTrack.getSampleRate() * 2); + long len = (long) audioDurationInSeconds; + if(len<1){ + len = 1; + } + try { + Thread.sleep(len); + Log.e(TAG,"playState---"+len); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + audioTrack.stop(); + if(playList.size()>0){ + play(playList.get(0)); + playList.remove(0); + } + + + } + }).start(); + + + } + + } + } + + public void stop() { + if (audioTrack != null) { + // 停止并释放资源 + audioTrack.stop(); + audioTrack.release(); + audioTrack = null; + } + } + + + +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java new file mode 100644 index 0000000..e25aedd --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/AudioRecorderMan.java @@ -0,0 +1,86 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.util.Log; + +import androidx.core.app.ActivityCompat; + +public class AudioRecorderMan { + + private String TAG = "AudioRecorder"; + private AudioRecord audioRecord; + private int bufferSize; + private boolean isRecording = false; + + private static AudioRecorderMan sInstance; + public static AudioRecorderMan getInstance() { + if (sInstance == null) { + synchronized (AudioRecorderMan.class) { + if (null == sInstance) + sInstance = new AudioRecorderMan(); + } + } + + return sInstance; + } + + public void startRecording(Context context) { + int sampleRate = 16000; // 采样率 + int channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道 + int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 格式 + bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); + + if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.RECORD_AUDIO) + != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG,"startRecording--no Permission"); + return ; + } + audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, + sampleRate, channelConfig, audioFormat, bufferSize); + if (audioRecord != null) { + isRecording = true; + Log.d(TAG,"startRecording--"); + new Thread(() -> { + audioRecord.startRecording(); + byte[] buffer = new byte[bufferSize]; + int read = 0; + while (read>=0) { + read = audioRecord.read(buffer, 0, bufferSize); + Log.d(TAG,"startRecording--"+read); + if (read < 0) { + // 处理错误 + } else { + // 处理buffer中的数据,这里你可以将它传输或者保存 + if(onBuffChange!=null){ + onBuffChange.onChange(buffer); + } + } + } + + }, "AudioRecorderThread").start(); + } + } + + public void stopRecording() { + Log.d(TAG,"stopRecording--"); + isRecording = false; + if (audioRecord != null) { + audioRecord.stop(); + audioRecord.release(); + } + } + + private onBuffChange onBuffChange; + + public void setOnBuffChange(AudioRecorderMan.onBuffChange onBuffChange) { + this.onBuffChange = onBuffChange; + } + + interface onBuffChange{ + void onChange(byte[] data); + } +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/ChatActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/ChatActivity.java new file mode 100644 index 0000000..c902afd --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/ChatActivity.java @@ -0,0 +1,237 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.Toast; + +import com.zhixun.android.sdk.polymerizesdk.adapter.MsgAdapter; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.callback.IAudioConvertListener; +import com.zhixun.android.sdk.polysdk.callback.OnChatMsgListener; +import com.zhixun.android.sdk.polysdk.callback.OnTranscriptionDataChange; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +public class ChatActivity extends AppCompatActivity { + + private String TAG = "ChatActivity"; + private EditText ed_content; + private RecyclerView msg_listview; + private MsgAdapter msgAdapter; + private String chatType = ""; + private int chatPosition = -1; + private Button btn_transcrip; + private boolean isStartTranscrip = false; + private StringBuffer speedSb = new StringBuffer(); + private StringBuffer chatBuff = new StringBuffer(); + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); + ed_content = findViewById(R.id.ed_content); + msg_listview = findViewById(R.id.msg_listview); + btn_transcrip = findViewById(R.id.btn_transcrip); + msgAdapter = new MsgAdapter(this,new ArrayList<>()); + msg_listview.setAdapter(msgAdapter); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + msg_listview.setLayoutManager(layoutManager); + + PolymerizeAgent.getInstance().getAiAPI().startTrans(); + + PolymerizeAgent.getInstance().getAiAPI().setOnChatMsgListener(new OnChatMsgListener() { + @Override + public void onChange(String type, String text) { + + chatType = type; + + if(chatType.equals("start")){ + msg_listview.post(new Runnable() { + @Override + public void run() { + chatPosition = msgAdapter.addData(""); + + } + }); + + Log.i(TAG,"onChange--"+chatPosition); + }else if(chatType.equals("end")){ + chatPosition = -1; + chatBuff = new StringBuffer(); + }else { + if(!TextUtils.isEmpty(text)){ + msg_listview.post(new Runnable() { + @Override + public void run() { + chatBuff.append(text); + if(chatPosition==-1){ + chatPosition = msgAdapter.addData(chatBuff.toString()); + }else { + msgAdapter.setData(chatPosition,chatBuff.toString()); + } + Log.i(TAG,"onChange--"+chatPosition); + msgAdapter.notifyItemChanged(chatPosition); + + + } + }); + + } + } + + } + }); + + btn_transcrip.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + speedSb = new StringBuffer(); + AudioRecorderMan.getInstance().startRecording(ChatActivity.this); + return false; + } + }); + btn_transcrip.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()){ + case MotionEvent.ACTION_UP: + if(isStartTranscrip){ + isStartTranscrip = false; + AudioRecorderMan.getInstance().stopRecording(); + } + break; + } + return false; + } + }); + + AudioRecorderMan.getInstance().setOnBuffChange(new AudioRecorderMan.onBuffChange() { + @Override + public void onChange(byte[] data) { + if(isStartTranscrip){ + PolymerizeAgent.getInstance().getAiAPI().sendTransByte(data); + } + } + }); + + PolymerizeAgent.getInstance().getAiAPI().setOnTranscriptionDataChange(new OnTranscriptionDataChange() { + @Override + public void onStartChange(boolean state) { + isStartTranscrip = state; + } + + @Override + public void onChange(String state, String msg) { + if(state.equals("end")){ + speedSb.append(msg); + Log.i(TAG,"onChange--"+msg); + runOnUiThread(new Runnable() { + @Override + public void run() { + ed_content.setText(speedSb.toString()); + + } + }); + } + + } + + }); + } + + public void back(View view){ + finish(); + } + public void sendChat(View view){ + if(chatType.equals("start")){ + Toast.makeText(this,"正在回答,请稍后再发送",Toast.LENGTH_SHORT).show(); + return; + } + String msg = ed_content.getText().toString(); + msgAdapter.addData(msg); + ed_content.setText(""); + PolymerizeAgent.getInstance().getAiAPI().sendChatMsg(msg); + + } + + private String API_KEY = "sk-proj-fdifVB2nPBIVcQeegE0AT3BlbkFJsgOXO5mnrmzox8pnSxMV"; + public void setAPIKEY(View view){ + if(chatType.equals("start")){ + Toast.makeText(this,"正在回答,请稍后再发送",Toast.LENGTH_SHORT).show(); + return; + } + + PolymerizeAgent.getInstance().getAuthenAPI().setAIChannelKey("CHAT GPT",API_KEY); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + PolymerizeAgent.getInstance().getAiAPI().stopTrans(); + } + + public void smbcTopcm(View view){ + String in = "/sdcard/Android/data/com.zhixun.android.sdk.polymerizesdk/files/input.msbc"; + String out = "/sdcard/Android/data/com.zhixun.android.sdk.polymerizesdk/files/out.pcm"; + File infile = new File(in); + byte[] indata = readFile(infile); + + PolymerizeAgent.getInstance().getAiAPI().convertAudioMsbcToPcm(indata, "16000","1", new IAudioConvertListener() { + + @Override + public void onError(String t) { + Log.i(TAG,"onError--"+t); + } + + @Override + public void onSuccess(String message) { + Log.i(TAG,"onSuccess--"+message); + } + + @Override + public void onSuccess(byte[] outputData) { + Log.i(TAG,"onSuccess--"+outputData.length); + PolymerizeAgent.getInstance().getAiAPI().sendTransByte(outputData); + + } + }); + + } + + + private byte[] readFile(File file) { + try { + InputStream in = new FileInputStream(file); + byte[] filecontent = new byte[in.available()]; + in.read(filecontent); + + Log.i(TAG, "readFile--" + filecontent.length); + in.close(); + return filecontent; + } catch (FileNotFoundException e) { + e.printStackTrace(); + Log.i(TAG, "readFile---" + e.getMessage()); + return null; + } catch (IOException e) { + e.printStackTrace(); + Log.i(TAG, "readFile---" + e.getMessage()); + return null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MainActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MainActivity.java new file mode 100644 index 0000000..a4561fa --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/MainActivity.java @@ -0,0 +1,233 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import com.zhixun.android.sdk.polymerizesdk.util.PermissionUtil; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.callback.AuthCallback; +import com.zhixun.android.sdk.polysdk.callback.HttRequestCallback; +import com.zhixun.android.sdk.polysdk.callback.IAudioConvertListener; +import com.zhixun.android.sdk.polysdk.gpt.ChatGPTClient; +import com.zhixun.android.sdk.polysdk.util.AESUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class MainActivity extends AppCompatActivity { + + private String TAG = "TAG_MainActivity"; + private int PERMISSION_REQUEST_CODE = 1000; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + if (!PermissionUtil.checkBluePermission(MainActivity.this)) { + String[] arr = PermissionUtil.getPerList(); + Log.d(TAG,"arr--"+arr); + ActivityCompat.requestPermissions(MainActivity.this,arr, PERMISSION_REQUEST_CODE); + Log.d(TAG, "No ble permission"); + } + + } + + + public void goChat(View view){ + if(!isLogin){ + Toast.makeText(this,"请先鉴权",Toast.LENGTH_SHORT).show(); + return; + } + startActivity(new Intent(this, ChatActivity.class)); + + + + + } + public void goTranslate(View view){ + if(!isLogin){ + Toast.makeText(this,"请先鉴权",Toast.LENGTH_SHORT).show(); + return; + } + startActivity(new Intent(this, TranslateActivity.class)); + } + public void goAigc(View view){ + if(!isLogin){ + Toast.makeText(this,"请先鉴权",Toast.LENGTH_SHORT).show(); + return; + } + startActivity(new Intent(this, AigcActivity.class)); + } + + public void goAsr(View view){ + if(!isLogin){ + Toast.makeText(this,"请先鉴权",Toast.LENGTH_SHORT).show(); + return; + } + startActivity(new Intent(this, AsrActivity.class)); + } + + public void onespeed(View view){ + if(!isLogin){ + Toast.makeText(this,"请先鉴权",Toast.LENGTH_SHORT).show(); + return; + } + String path = "/sdcard/Android/data/com.zhixun.android.sdk.polymerizesdk/files/tts.mp3"; + ChatGPTClient.getInstance().sendAudioForCompletion(new File(path), new HttRequestCallback() { + @Override + public void onSuccess(String result) { + Log.d(TAG, "onSuccess--"+result); + } + + @Override + public void onFail(String msg) { + Log.d(TAG, "onFail--"+msg); + } + }); + + } + + public void goRegiest(View view){ + PolymerizeAgent.getInstance().getAuthenAPI().regiest("HHosiYUNdG42t1cTgKOzIUPOvAVMI2QT" + , "281106AFB0F7", "pafOCKLiUbeVHbdZlddH", new AuthCallback() { + @Override + public void onSuccess(String result) { + Log.i("goRegiest","result--"+result); + } + + @Override + public void onFail(String msg) { + Log.i("goRegiest","onFail--"+msg); + } + }); + + } + + private boolean isLogin = false; + /*battery_power = 35 + CPI = 1000 + CPI_list = 600,800,1000,1300,1600 + version = v1.24.06.05 + brand = vmouse123 + sn = MSCL1BKZ12105000042363 + mac = C0310000A57B + productKey = ccvUoJOLbXn + secretKey = nNRjkRpKTxvprGaW + deviceSecret = ZqqFHYeXf4xuv5jEfuHUE2hdMnoaegGi*/ + public void goLogin(View view){ + PolymerizeAgent.getInstance().getAuthenAPI().authentication("281106AFB0F7" + , "F1xdqQL2fXjcmD4dV4To42dUUiBb2L", "HHosiYUNdG42t1cTgKOzIUPOvAVMI2QT", new AuthCallback() { + @Override + public void onSuccess(String result) { + isLogin = true; + Log.i("goLogin","result--"+result); + } + + @Override + public void onFail(String msg) { + Log.i("goLogin","onFail--"+msg); + } + }); + /*String pwd = "RDSr+qCM3zLqTLVh3L/74B4Rhh5CsBU7D3/0KZMCknM="; + String nonce = "WFY51NbA4lUff3Jd"; + String key = "HHosiYUNdG42t1cTgKOzIUPOvAVMI2QT"; + + *//*if(key.length()>16){ + key = key.substring(0,16); + }*//* + Log.i(TAG,key+"--key---"+key.length()); + String ds = AESUtil.decrypt(pwd,key,nonce); + Log.i(TAG,"ds---"+ds); + + String pwdm = AESUtil.encrypt(ds,key,nonce); + + Log.i(TAG,"pwdm---"+pwdm);*/ + } + + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Log.d(TAG, "onRequestPermissionsResult requestCode--" + requestCode); + if (requestCode == PERMISSION_REQUEST_CODE) { + if (grantResults.length > 0) { + Log.d(TAG, "onRequestPermissionsResult granted"); + for (int i=0;i 0) { + playData(sourceList.get(0)); + sourceList.remove(0); + } + } + }); + } + + private List sourceList = new ArrayList<>(); + + public void playData(byte[] audioSource) { + Log.i(TAG,"playData--"+mediaPlayer.isPlaying()+"--size--"+audioSource.length); + new Thread(new Runnable() { + @Override + public void run() { + if (mediaPlayer.isPlaying()) { + try { + File tempMp3 = File.createTempFile("temp_" + System.currentTimeMillis(), ".mp3"); +// tempMp3.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(tempMp3); + fos.write(audioSource); + fos.close(); + FileInputStream fis = new FileInputStream(tempMp3); + sourceList.add(fis); + } catch (IOException ex) { + String s = ex.toString(); + Log.d(TAG, "playData--" + s); + ex.printStackTrace(); + } + + } else { + try { + File tempMp3 = File.createTempFile("temp_" + System.currentTimeMillis(), ".mp3"); + tempMp3.deleteOnExit(); + Log.i(TAG,"playData-11-"); + FileOutputStream fos = new FileOutputStream(tempMp3); + fos.write(audioSource); + fos.close(); + Log.i(TAG,"playData-22-"); + mediaPlayer.reset(); + FileInputStream fis = new FileInputStream(tempMp3); + Log.i(TAG,"playData-33-"); + mediaPlayer.setDataSource(fis.getFD()); + mediaPlayer.prepare(); + mediaPlayer.start(); + Log.i(TAG,"playData-44-"); + } catch (IOException ex) { + String s = ex.toString(); + Log.d(TAG, "playData-1-" + s); + ex.printStackTrace(); + } + + } + + } + }).run(); + + } + + public void playData(FileInputStream fis) { + + try { + mediaPlayer.setDataSource(fis.getFD()); + mediaPlayer.prepare(); + mediaPlayer.start(); + } catch (Exception ex) { + String s = ex.toString(); + Log.d(TAG, "playData-2-" + s); + ex.printStackTrace(); + } + + } + + public void playData(String path) { + stop(); + initMedia(); + try { + mediaPlayer.setDataSource(path); + mediaPlayer.prepare(); + mediaPlayer.start(); + } catch (Exception ex) { + String s = ex.toString(); + Log.d(TAG, "playData-2-" + s); + ex.printStackTrace(); + } + + } + + public void stop() { + mediaPlayer.stop(); + mediaPlayer.release(); + } + +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/TranslateActivity.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/TranslateActivity.java new file mode 100644 index 0000000..c053c8f --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/TranslateActivity.java @@ -0,0 +1,108 @@ +package com.zhixun.android.sdk.polymerizesdk; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.zhixun.android.sdk.polymerizesdk.adapter.MsgAdapter; +import com.zhixun.android.sdk.polysdk.PolymerizeAgent; +import com.zhixun.android.sdk.polysdk.callback.AIRequestCallback; +import com.zhixun.android.sdk.polysdk.entity.SupportLanguage; + +import java.util.ArrayList; +import java.util.List; + +public class TranslateActivity extends AppCompatActivity { + + private String TAG = "TranslateActivity"; + private EditText ed_content; + private RecyclerView msg_listview; + private MsgAdapter msgAdapter; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_translate); + ed_content = findViewById(R.id.ed_content); + msg_listview = findViewById(R.id.msg_listview); + msgAdapter = new MsgAdapter(this,new ArrayList<>()); + msg_listview.setAdapter(msgAdapter); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + msg_listview.setLayoutManager(layoutManager); + } + public void back(View view){ + finish(); + } + + public void translateTest(View view){ + String msg = ed_content.getText().toString(); + if(TextUtils.isEmpty(msg)){ + Toast.makeText(this,"请输入你要翻译的内容",Toast.LENGTH_SHORT).show(); + return; + } + //msgAdapter.addData(msg); + PolymerizeAgent.getInstance().getAiAPI().translate("en", msg, new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + String resultStr = (String) result; + runOnUiThread(new Runnable() { + @Override + public void run() { + msgAdapter.addData(msg+":"+resultStr); + + } + }); + Log.i(TAG,"resultStr--"+resultStr); + } + + @Override + public void onFail(String msg) { + + } + }); + } + + public void getlangList(View view){ + PolymerizeAgent.getInstance().getAiAPI().getSupportLan(new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + Log.i(TAG,"getSupportLan--"+new Gson().toJson(result)); + + runOnUiThread(new Runnable() { + @Override + public void run() { + msgAdapter.addData(new Gson().toJson(result)); + + } + }); + + } + + @Override + public void onFail(String msg) { + + } + }); + } + + public void checkLan(View view){ + PolymerizeAgent.getInstance().getAiAPI().detectLanguage("hello",new AIRequestCallback() { + @Override + public void onSuccess(Object result) { + Log.i(TAG,"detectLanguage--"+new Gson().toJson(result)); + } + + @Override + public void onFail(String msg) { + + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/MsgAdapter.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/MsgAdapter.java new file mode 100644 index 0000000..e0ca19a --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/adapter/MsgAdapter.java @@ -0,0 +1,78 @@ +package com.zhixun.android.sdk.polymerizesdk.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.zhixun.android.sdk.polymerizesdk.R; + +import java.util.ArrayList; + +public class MsgAdapter extends RecyclerView.Adapter { + + private ArrayList msgList ; + private Context mContext; + public MsgAdapter(Context context, ArrayList msgList) { + this.mContext = context; + this.msgList = msgList; + } + + @NonNull + @Override + public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = View.inflate(mContext, R.layout.layout_item_msg, null); + MyViewHoder myViewHoder = new MyViewHoder(view); + return myViewHoder; + } + + @Override + public void onBindViewHolder(@NonNull MyViewHoder holder, int position) { + String msg = msgList.get(position); + holder.tvMsg.setText(msg); + + } + + @Override + public int getItemCount() { + return msgList.size(); + } + + + private void addData(ArrayList data){ + msgList.addAll(data); + notifyDataSetChanged(); + } + + public int addData(String data){ + msgList.add(data); + notifyDataSetChanged(); + return msgList.size()-1; + } + + public void setData(int position,String data){ + msgList.set(position,data); +// notifyItemChanged(position); + } + + public ArrayList getMsgList() { + return msgList; + } + + public class MyViewHoder extends RecyclerView.ViewHolder { + TextView tvMsg; + public MyViewHoder(@NonNull View itemView) { + super(itemView); + tvMsg = itemView.findViewById(R.id.tv_msg); + + } + + } + +} diff --git a/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/PermissionUtil.java b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/PermissionUtil.java new file mode 100644 index 0000000..77dfa4e --- /dev/null +++ b/app/src/main/java/com/zhixun/android/sdk/polymerizesdk/util/PermissionUtil.java @@ -0,0 +1,48 @@ +package com.zhixun.android.sdk.polymerizesdk.util; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import android.Manifest; +import android.content.Context; +import android.os.Build; + +import androidx.core.content.ContextCompat; + +import java.util.ArrayList; + +public class PermissionUtil { + + + private static ArrayList needPerList = new ArrayList<>(); + + public static String[] getPerList(){ + return needPerList.toArray(new String[0]); + } + public static boolean checkBluePermission(Context context) { + String[] perList = new String[]{ + Manifest.permission.WRITE_EXTERNAL_STORAGE + ,Manifest.permission.MANAGE_EXTERNAL_STORAGE}; + + /*if (Build.VERSION.SDK_INT >=26&&Build.VERSION.SDK_INT <31){ + perList = new String[]{ + Manifest.permission.WRITE_EXTERNAL_STORAGE}; + }else if (Build.VERSION.SDK_INT >=31){ + perList = new String[]{ + Manifest.permission.WRITE_EXTERNAL_STORAGE}; + }*/ + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + + for (int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_aigc.xml b/app/src/main/res/layout/activity_aigc.xml new file mode 100644 index 0000000..a79d4b1 --- /dev/null +++ b/app/src/main/res/layout/activity_aigc.xml @@ -0,0 +1,58 @@ + + + +