diff --git a/JavaLib/build.gradle b/JavaLib/build.gradle index 113ac4d..23d62d3 100644 --- a/JavaLib/build.gradle +++ b/JavaLib/build.gradle @@ -1,11 +1,33 @@ apply plugin: 'java-library' +apply plugin: 'kotlin' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // https://mvnrepository.com/artifact/org.ow2.asm/asm // compile group: 'org.ow2.asm', name: 'asm', version: '7.2' compile "org.ow2.asm:asm:7.2" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" } -sourceCompatibility = "7" -targetCompatibility = "7" +buildscript { + ext.kotlin_version = '1.3.60' + repositories { + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +repositories { + mavenCentral() +} +compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} +compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} diff --git a/JavaLib/src/main/java/com/baiiu/java/Child.java b/JavaLib/src/main/java/com/baiiu/java/Child.java index 480d6a1..8e58243 100644 --- a/JavaLib/src/main/java/com/baiiu/java/Child.java +++ b/JavaLib/src/main/java/com/baiiu/java/Child.java @@ -12,6 +12,7 @@ public class Child extends Parent { public static int b = 10; public int c = 10; + private final Object object; static { System.out.println("Child静态代码块 ==== " + b++); @@ -21,9 +22,9 @@ public class Child extends Parent { System.out.println("Child构造代码块 ==== " + b++ + ", " + c++); } - public Child() { System.out.println("Child构造函数 ==== " + b++ + ", " + c++); + object = "123"; } @Override diff --git a/JavaLib/src/main/java/com/baiiu/java/TestLazy.kt b/JavaLib/src/main/java/com/baiiu/java/TestLazy.kt new file mode 100644 index 0000000..76f6341 --- /dev/null +++ b/JavaLib/src/main/java/com/baiiu/java/TestLazy.kt @@ -0,0 +1,30 @@ +package com.baiiu.java + +open class ParentA { + init { + println("ParentA构造") + aaaaa() + } + open fun aaaaa() { + } +} +class ChildA : ParentA() { + private val a by lazy { 1 } + init { + println("ChildA构造") + } + override fun aaaaa() { + println(a) + } +} +class TeastSafe { + private val a by lazy { 1 } + + init { + println(a) + } +} +fun main(args: Array) { + TeastSafe() + ChildA() +} \ No newline at end of file diff --git a/JavaLib/src/main/java/com/baiiu/java/testEnum/EnumTest.java b/JavaLib/src/main/java/com/baiiu/java/testEnum/EnumTest.java new file mode 100644 index 0000000..e360e25 --- /dev/null +++ b/JavaLib/src/main/java/com/baiiu/java/testEnum/EnumTest.java @@ -0,0 +1,33 @@ +package com.baiiu.java.testEnum; + +/** + * Created by zhuzhe.zz on 2024/6/28 + * + * @author zhuzhe.zz@bytedance.com + */ +public class EnumTest { + public State state = State.ONE; + public State2 state2 = State2.ONE2; + public State3 state3 = State3.ONE3; + + public enum State { + ONE, TWO, Three, Four, Five + } + + public enum State2 { + ONE2, TWO2, Three2, Four2, Five2 + } + + public enum State3 { + ONE3, TWO3, Three3, Four3, Five3 + } + + @Override + public String toString() { + return "EnumTest{" + + "state=" + state + + ", state2=" + state2 + + ", state3=" + state3 + + '}'; + } +} diff --git a/JavaLib/src/main/java/com/baiiu/java/testEnum/Test.java b/JavaLib/src/main/java/com/baiiu/java/testEnum/Test.java new file mode 100644 index 0000000..86167e2 --- /dev/null +++ b/JavaLib/src/main/java/com/baiiu/java/testEnum/Test.java @@ -0,0 +1,27 @@ +package com.baiiu.java.testEnum; + +/** + * Created by zhuzhe.zz on 2024/6/28 + * + * @author zhuzhe.zz@bytedance.com + */ +public class Test { + + public static void main(String[] args) { + EnumTest enumTest = new EnumTest(); + EnumTest enumTest1 = new EnumTest(); + EnumTest enumTest2 = new EnumTest(); + + System.out.println("Test::: " + enumTest + ", " + enumTest1 + ", " + enumTest2); + System.out.println("Test::: " + (enumTest.state == enumTest1.state) + ", " + (enumTest1.state == enumTest2.state)); + + int i; + for (i = 0; i < 10; ++i) { + if (i == 5){ + break; + } + } + System.out.println("i = " + i); + } + +} diff --git a/build.gradle b/build.gradle index 6f64644..67ebf34 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8dacc3a..521e2f7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Sep 11 11:42:14 CST 2019 +#Fri Jan 03 12:19:49 CST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/jni/cmaketest/src/main/cpp/native-lib.cpp b/jni/cmaketest/src/main/cpp/native-lib.cpp index 89f5ae3..68e6953 100644 --- a/jni/cmaketest/src/main/cpp/native-lib.cpp +++ b/jni/cmaketest/src/main/cpp/native-lib.cpp @@ -11,6 +11,11 @@ #endif + +void testBoolean(bool rtt) { + __android_log_print(ANDROID_LOG_ERROR, "mLogU", "testBoolean: %d", rtt); +} + extern "C" JNIEXPORT jstring JNICALL Java_com_baiiu_cmaketest_MainActivity_hello(JNIEnv *env, jobject thiz) { @@ -24,5 +29,15 @@ Java_com_baiiu_cmaketest_MainActivity_hello(JNIEnv *env, jobject thiz) { __android_log_print(ANDROID_LOG_ERROR, "mLogU", "log: %d", test(5)); #endif + jclass cls = env->GetObjectClass(thiz); + + jmethodID callJavaMethodId = env->GetMethodID(cls, "cCallJava", "(ZJ)V"); + jboolean b = 199; // 报错 + jlong l = 1; + + testBoolean(199); + env->CallVoidMethod(thiz, callJavaMethodId, b ? JNI_TRUE : JNI_FALSE, l); + + return env->NewStringUTF("hello"); } \ No newline at end of file diff --git a/jni/cmaketest/src/main/java/com/baiiu/cmaketest/MainActivity.java b/jni/cmaketest/src/main/java/com/baiiu/cmaketest/MainActivity.java index bf78d1a..7989b13 100644 --- a/jni/cmaketest/src/main/java/com/baiiu/cmaketest/MainActivity.java +++ b/jni/cmaketest/src/main/java/com/baiiu/cmaketest/MainActivity.java @@ -18,4 +18,8 @@ protected void onCreate(Bundle savedInstanceState) { } private native String hello(); + + private void cCallJava(boolean bool, long number) { + android.util.Log.e("mLogU", bool + ", " + number); + } } \ No newline at end of file diff --git a/jni/jnitest/src/main/cpp/dns/testdns.cpp b/jni/jnitest/src/main/cpp/dns/testdns.cpp index e68194d..8071837 100644 --- a/jni/jnitest/src/main/cpp/dns/testdns.cpp +++ b/jni/jnitest/src/main/cpp/dns/testdns.cpp @@ -58,11 +58,11 @@ JNIEXPORT void JNICALL Java_com_baiiu_jnitest_dns_DNSFragment_nativeTest4_11935(JNIEnv *env, jobject thiz) { struct addrinfo hints = {0}, *ai, *cur_ai; hints.ai_family = AF_INET; // 为0表示v4和v6都去查找 -// hints.ai_socktype = SOCK_STREAM; + hints.ai_socktype = SOCK_STREAM; const char *hostname = "mtplatform-tx-flv.meituan.net"; char portstr[10]; - int port = 1935; + int port = 443; snprintf(portstr, sizeof(portstr), "%d", port); int64_t dns_starttime = av_gettime_relative(); diff --git a/settings.gradle b/settings.gradle index c9e4490..a7199b4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,3 @@ -include ':jni:nativeleak' import java.util.function.Consumer /* @@ -11,7 +10,7 @@ include( // ':plugin:pluginApplication', // ':plugin:logkotplugin', - // ':JavaLib', + ':JavaLib', // ':plugin:testplugin', // ':plugin:testKotlinPlugin', @@ -23,7 +22,8 @@ include( ':hook:testapk', ":jni:jnitest", ':jni:mktest', - ':jni:cmaketest' + ':jni:cmaketest', + ':jni:nativeleak' ) @@ -49,7 +49,7 @@ include( // ":someApplications:ptr-lib", // ":someApplications:touchEventStudy", ':someApplications:researchStudy', - + ':someApplications:multiprocess' ) diff --git a/someApplications/multiprocess/.gitignore b/someApplications/multiprocess/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/someApplications/multiprocess/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/someApplications/multiprocess/IBookManager.java b/someApplications/multiprocess/IBookManager.java new file mode 100644 index 0000000..b8e67e1 --- /dev/null +++ b/someApplications/multiprocess/IBookManager.java @@ -0,0 +1,149 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Original file: /Users/baiiu/Desktop/MutiProcessTest/app/src/main/aidl/com/baiiu/mutiprocess/IBookManager.aidl + */ +package com.baiiu.mutiprocess; + +public interface IBookManager extends android.os.IInterface { + /** Local-side IPC implementation stub class. */ + public static abstract class Stub extends android.os.Binder implements com.baiiu.mutiprocess.IBookManager { + // Binder的唯一标识 + private static final java.lang.String DESCRIPTOR = "com.baiiu.mutiprocess.IBookManager"; + + /** Construct the stub at attach it to the interface. */ + public Stub() { + this.attachInterface(this, DESCRIPTOR); + } + + /** + * Cast an IBinder object into an com.baiiu.mutiprocess.IBookManager interface, + * generating a proxy if needed. + */ + // 将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象 + // 这种转换是区分进程的 + public static com.baiiu.mutiprocess.IBookManager asInterface(android.os.IBinder obj) { //BinderProxy + if ((obj == null)) { + return null; + } + android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); + if (((iin != null) && (iin instanceof com.baiiu.mutiprocess.IBookManager))) { + // 同一进程,返回的就是服务端的Stub对象本身 + return ((com.baiiu.mutiprocess.IBookManager) iin); + } + + // 不同进程,返回系统封装后的Proxy对象 + return new com.baiiu.mutiprocess.IBookManager.Stub.Proxy(obj); + } + + // 返回当前Binder对象 + @Override public android.os.IBinder asBinder() { + return this; + } + + // 运行在服务端中的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过这个系统底层封装后交由此方法处理。 + // 1. 服务端从code可以确定客户端所请求的目标方法是什么 + // 2. 接着从data中去除目标方法所需的参数(如果有),然后执行目标方法 + // 3. 执行完毕后,就像reply中写入返回值(如果有), + // 如果此方法返回false,表示客户端请求失败。可以使用这个特性来做权限验证,以使随便一个进程不能调用我们的服务。 + @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, + int flags) throws android.os.RemoteException { + switch (code) { + case INTERFACE_TRANSACTION: { + reply.writeString(DESCRIPTOR); + return true; + } + case TRANSACTION_getBookList: { + data.enforceInterface(DESCRIPTOR); + java.util.List _result = this.getBookList(); + reply.writeNoException(); + reply.writeTypedList(_result); + return true; + } + case TRANSACTION_addBook: { + data.enforceInterface(DESCRIPTOR); + com.baiiu.mutiprocess.Book _arg0; + if ((0 != data.readInt())) { + _arg0 = com.baiiu.mutiprocess.Book.CREATOR.createFromParcel(data); + } else { + _arg0 = null; + } + this.addBook(_arg0); + reply.writeNoException(); + return true; + } + } + return super.onTransact(code, data, reply, flags); + } + + private static class Proxy implements com.baiiu.mutiprocess.IBookManager { + private android.os.IBinder mRemote; + + Proxy(android.os.IBinder remote) { + mRemote = remote; + } + + @Override public android.os.IBinder asBinder() { + return mRemote; + } + + public java.lang.String getInterfaceDescriptor() { + return DESCRIPTOR; + } + + /* + 运行在客户端,当客户端远程调用此方法时,内部实现: + + 1. 创建该方法需要的输入型Parcel对象_data、输出型Parcel对象_reply和返回值对象List + 2. 将该方法的参数信息写入_data中(如果有) + 3. 调用transact方法发起RPC请求,BinderProxy跨进程,同时挂起当前线程 + 4. 服务端的onTransact方法被调用 + 5. 直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果 + 6. 返回_reply中的数据 + */ + @Override public java.util.List getBookList() throws android.os.RemoteException { + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + java.util.List _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArrayList(com.baiiu.mutiprocess.Book.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + /* + addBook没有返回值,所以不需要从_reply中取出返回值 + */ + @Override public void addBook(com.baiiu.mutiprocess.Book book) throws android.os.RemoteException { + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + if ((book != null)) { + _data.writeInt(1); + book.writeToParcel(_data, 0); + } else { + _data.writeInt(0); + } + mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } + } + + static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); + static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); + } + + public java.util.List getBookList() throws android.os.RemoteException; + + public void addBook(com.baiiu.mutiprocess.Book book) throws android.os.RemoteException; +} diff --git a/someApplications/multiprocess/build.gradle b/someApplications/multiprocess/build.gradle new file mode 100644 index 0000000..511142b --- /dev/null +++ b/someApplications/multiprocess/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion rootProject.ext.compileSdkVersion as Integer + buildToolsVersion rootProject.ext.buildToolsVersion as String + + + defaultConfig { + applicationId "com.baiiu.multiprocess" + minSdkVersion rootProject.ext.minSdkVersion as int + targetSdkVersion rootProject.ext.targetSdkVersion as int + versionCode 1 + versionName "1.0" + + 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 { + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + implementation rootProject.ext.support.appcompat + implementation project(":lib_component:LogUtil") +} \ No newline at end of file diff --git a/someApplications/multiprocess/proguard-rules.pro b/someApplications/multiprocess/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/someApplications/multiprocess/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/someApplications/multiprocess/src/androidTest/java/com/baiiu/multiprocess/ExampleInstrumentedTest.java b/someApplications/multiprocess/src/androidTest/java/com/baiiu/multiprocess/ExampleInstrumentedTest.java new file mode 100644 index 0000000..971728d --- /dev/null +++ b/someApplications/multiprocess/src/androidTest/java/com/baiiu/multiprocess/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.baiiu.multiprocess; + +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.baiiu.multiprocess", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/AndroidManifest.xml b/someApplications/multiprocess/src/main/AndroidManifest.xml new file mode 100644 index 0000000..80dcf28 --- /dev/null +++ b/someApplications/multiprocess/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/Book.aidl b/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/Book.aidl new file mode 100644 index 0000000..fe46387 --- /dev/null +++ b/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/Book.aidl @@ -0,0 +1,2 @@ +package com.baiiu.multiprocess; +parcelable Book; diff --git a/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/IBookManager.aidl b/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/IBookManager.aidl new file mode 100644 index 0000000..564e0eb --- /dev/null +++ b/someApplications/multiprocess/src/main/aidl/com/baiiu/multiprocess/IBookManager.aidl @@ -0,0 +1,8 @@ +package com.baiiu.multiprocess; +import com.baiiu.multiprocess.Book; +import android.view.Surface; + +interface IBookManager { + List getBookList(); + void addBook(in Book book); +} \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/Book.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/Book.java new file mode 100644 index 0000000..93ace54 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/Book.java @@ -0,0 +1,51 @@ +package com.baiiu.multiprocess; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * author: baiiu + * date: on 17/12/27 16:32 + * description: + */ +public class Book implements Parcelable { + + public int bookId; + public String bookName; + + public Book() { + } + + public Book(int bookId, String bookName) { + this.bookId = bookId; + this.bookName = bookName; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(bookId); + out.writeString(bookName); + } + + public static final Creator CREATOR = new Creator() { + public Book createFromParcel(Parcel in) { + return new Book(in); + } + + public Book[] newArray(int size) { + return new Book[size]; + } + }; + + private Book(Parcel in) { + bookId = in.readInt(); + bookName = in.readString(); + } + + @Override public String toString() { + return String.format("[bookId:%s, bookName:%s]", bookId, bookName); + } +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/BookManagerService.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/BookManagerService.java new file mode 100644 index 0000000..331e6e7 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/BookManagerService.java @@ -0,0 +1,64 @@ +package com.baiiu.multiprocess; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.os.Process; +import android.os.RemoteException; + +import androidx.annotation.Nullable; + +import com.baiiu.library.LogUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * author: baiiu + * date: on 17/12/27 17:15 + * description: + */ +public class BookManagerService extends Service { + public static final String TAG_BINDER = "binder"; + + private final List list = new ArrayList<>(); + +// private Binder mBinder = new BookManagerImpl(); + private Binder mBinder = new IBookManager.Stub() { + + @Override + public List getBookList() throws RemoteException { + LogUtil.d(TAG_BINDER, "BookManagerService#getBookList: " + Thread.currentThread().getId() + ", " + Binder.getCallingPid() + "," + Process.myPid()); + synchronized (list) { + return list; + } + } + + @Override + public void addBook(Book book) throws RemoteException { + LogUtil.d(TAG_BINDER, "BookManagerService#addBook: " + Thread.currentThread().getId() + ", " + Binder.getCallingPid() + ", " + Process.myPid()); + + synchronized (list) { + list.add(book); + } + } + }; + + + @Override + public void onCreate() { + super.onCreate(); + list.add(new Book(1, "book1")); + list.add(new Book(2, "book2")); + list.add(new Book(3, "book3")); + } + + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MainActivity.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MainActivity.java new file mode 100644 index 0000000..1b43e12 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MainActivity.java @@ -0,0 +1,111 @@ +package com.baiiu.multiprocess; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Process; +import android.os.RemoteException; +import android.view.View; + +import androidx.appcompat.app.AppCompatActivity; + +import com.baiiu.library.LogUtil; + +import java.util.List; + +import static com.baiiu.multiprocess.BookManagerService.TAG_BINDER; + + +public class MainActivity extends AppCompatActivity { + private IBookManager mRemoteBookManager; + + private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { + @Override + public void binderDied() { + if (mRemoteBookManager == null) return; + + mRemoteBookManager.asBinder() + .unlinkToDeath(mDeathRecipient, 0); + mRemoteBookManager = null; + + Intent intent = new Intent(MainActivity.this, BookManagerService.class); + bindService(intent, connection, Context.BIND_AUTO_CREATE); + } + }; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + LogUtil.d(UserManager.INSTANCE.age + ", " + UserManager.sId); + UserManager.sId += 1; + UserManager.INSTANCE.age += 1; + LogUtil.d(UserManager.INSTANCE.age + ", " + UserManager.sId); + + LogUtil.d(TAG_BINDER, "MainActivity: " + Thread.currentThread().getId() + ", " + Process.myPid()); + } + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + /* + MainActivity: 2, 16377 + onServiceConnected#service: android.os.BinderProxy@1d3a70c, 2, 16377 // 回调到主线程 + BookManagerImpl#Proxy#addBook: 2, 16377 // 在主线程触发 + BookManagerImpl#onTransact: code is 2, 3553, 16407 // 在远端binder线程池里 + BookManagerService#addBook: 3553, 16377, 16407 + BookManagerImpl#Proxy#getBookList: 2, 16377 + BookManagerImpl#onTransact: code is 1, 3553, 16407 + BookManagerService#getBookList: 3553, 16377,16407 + */ + + LogUtil.d("onServiceConnected:" + name); // BinderProxy,只有这个才有跨进程的能力 + LogUtil.d(TAG_BINDER, "onServiceConnected#service: " + service + ", " + Thread.currentThread().getId() + ", " + Process.myPid()); + + mRemoteBookManager = IBookManager.Stub.asInterface(service); + try { + mRemoteBookManager.asBinder() + .linkToDeath(mDeathRecipient, 0); + + mRemoteBookManager.addBook(new Book(4, "book4")); + + List bookList = mRemoteBookManager.getBookList(); + + LogUtil.d(bookList); + + } catch (RemoteException e) { + LogUtil.e(e.toString()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + LogUtil.d("onServiceDisconnected:" + name); + mRemoteBookManager = null; + } + }; + + @Override + protected void onDestroy() { + super.onDestroy(); + if (connection != null) { + unbindService(connection); + } + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.tv_bind: + Intent intent = new Intent(this, BookManagerService.class); + bindService(intent, connection, Context.BIND_AUTO_CREATE); + break; + case R.id.tv_second: + startActivity(new Intent(this, SecondActivity.class)); + break; + } + } +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MyApplication.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MyApplication.java new file mode 100644 index 0000000..f3b369e --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/MyApplication.java @@ -0,0 +1,33 @@ +package com.baiiu.multiprocess; + +import android.app.Application; +import com.baiiu.library.LogUtil; + +/** + * author: baiiu + * date: on 17/12/27 15:39 + * description: + */ +public class MyApplication extends Application { + + @Override public void onCreate() { + super.onCreate(); + LogUtil.d("application onCreate"); + + //int pid = android.os.Process.myPid();//获取进程pid + //ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);//获取系统的ActivityManager服务 + //for (ActivityManager.RunningAppProcessInfo appProcess : am.getRunningAppProcesses()) { + // if (appProcess.pid == pid) { + // LogUtil.d("Process.myUid(): " + // + Process.myUid() + // + "," + // + "Process.myPid(): " + // + Process.myPid() + // + ", " + // + appProcess.processName); + // return; + // } + //} + } + +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/SecondActivity.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/SecondActivity.java new file mode 100644 index 0000000..dff168a --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/SecondActivity.java @@ -0,0 +1,29 @@ +package com.baiiu.multiprocess; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.baiiu.library.LogUtil; + +/** + * author: baiiu + * date: on 17/12/27 15:18 + * description: + */ +public class SecondActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_second); + LogUtil.d(UserManager.INSTANCE.age + ", " + UserManager.sId); + } + + public void onClick(View view) { + startActivity(new Intent(this, ThirdActivity.class)); + } +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/ThirdActivity.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/ThirdActivity.java new file mode 100644 index 0000000..d141c67 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/ThirdActivity.java @@ -0,0 +1,24 @@ +package com.baiiu.multiprocess; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.baiiu.library.LogUtil; + +/** + * author: baiiu + * date: on 17/12/27 15:19 + * description: + */ +public class ThirdActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_third); + LogUtil.d(UserManager.INSTANCE.age + ", " + UserManager.sId); + } + +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/UserManager.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/UserManager.java new file mode 100644 index 0000000..b44840a --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/UserManager.java @@ -0,0 +1,28 @@ +package com.baiiu.multiprocess; + +import android.os.Handler; +import android.os.Message; + +/** + * author: baiiu + * date: on 17/12/27 15:27 + * description: + */ +public enum UserManager { + INSTANCE; + + UserManager() { + //LogUtil.d("Looper.myLooper(): " + Looper.myLooper() == null); + } + + public int age = 1; + + public static int sId = 1; + + Handler handler = new Handler(new Handler.Callback() { + @Override public boolean handleMessage(Message msg) { + return false; + } + }); + +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManager.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManager.java new file mode 100644 index 0000000..5d2c545 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManager.java @@ -0,0 +1,27 @@ +package com.baiiu.multiprocess.custom; + +import android.os.IBinder; +import android.os.IInterface; +import android.os.RemoteException; + +import com.baiiu.multiprocess.Book; + +import java.util.List; + +/** + * author: baiiu + * date: on 18/1/3 14:25 + * description: + */ +public interface CustomBookManager extends IInterface { + + // Binder的唯一标识 + String DESCRIPTOR = "com.baiiu.mutiprocess.custom.IBookManager"; + + int TRANSACTION_getBookList = IBinder.FIRST_CALL_TRANSACTION + 0; + int TRANSACTION_addBook = IBinder.FIRST_CALL_TRANSACTION + 1; + + List getBookList() throws RemoteException; + + void addBook(Book book) throws RemoteException; +} diff --git a/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManagerImpl.java b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManagerImpl.java new file mode 100644 index 0000000..db8a461 --- /dev/null +++ b/someApplications/multiprocess/src/main/java/com/baiiu/multiprocess/custom/CustomBookManagerImpl.java @@ -0,0 +1,156 @@ +package com.baiiu.multiprocess.custom; + +import android.os.Binder; +import android.os.IBinder; +import android.os.IInterface; +import android.os.Parcel; +import android.os.Process; +import android.os.RemoteException; + +import com.baiiu.library.LogUtil; +import com.baiiu.multiprocess.Book; + +import java.util.List; + +import static com.baiiu.multiprocess.BookManagerService.TAG_BINDER; + +/** + * author: baiiu + * date: on 18/1/3 19:15 + * description: + */ +public abstract class CustomBookManagerImpl extends Binder implements CustomBookManager { + + protected CustomBookManagerImpl() { + this.attachInterface(this, DESCRIPTOR); + } + + @Override + public IBinder asBinder() { + return this; + } + + // 将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象 + // 这种转换是区分进程的 + public static CustomBookManager asInterface(android.os.IBinder obj) { + if (obj == null) return null; + + IInterface inn = obj.queryLocalInterface(DESCRIPTOR); + if (inn != null && inn instanceof CustomBookManager) { + return (CustomBookManager) inn; + } + + return new CustomBookManagerImpl.Proxy(obj); + } + + // 运行在服务端中的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过这个系统底层封装后交由此方法处理。 + // 1. 服务端从code可以确定客户端所请求的目标方法是什么 + // 2. 接着从data中去除目标方法所需的参数(如果有),然后执行目标方法 + // 3. 执行完毕后,就像reply中写入返回值(如果有), + // 如果此方法返回false,表示客户端请求失败。可以使用这个特性来做权限验证,以使随便一个进程不能调用我们的服务。 + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + LogUtil.d(TAG_BINDER, "BookManagerImpl#onTransact: code is " + code + ", " + Thread.currentThread().getId() + ", " + Process.myPid()); + + switch (code) { + case INTERFACE_TRANSACTION: { + reply.writeString(DESCRIPTOR); + return true; + } + case TRANSACTION_getBookList: { + data.enforceInterface(DESCRIPTOR); + java.util.List _result = this.getBookList(); + reply.writeNoException(); + reply.writeTypedList(_result); + return true; + } + case TRANSACTION_addBook: { + data.enforceInterface(DESCRIPTOR); + Book _arg0; + if ((0 != data.readInt())) { + _arg0 = Book.CREATOR.createFromParcel(data); + } else { + _arg0 = null; + } + this.addBook(_arg0); + reply.writeNoException(); + return true; + } + } + + return super.onTransact(code, data, reply, flags); + } + + private static class Proxy implements CustomBookManager { + private IBinder mRemote; + + Proxy(IBinder remote) { + this.mRemote = remote; + } + + @Override + public IBinder asBinder() { + return mRemote; + } + + public String getInterfaceDescriptor() { + return DESCRIPTOR; + } + + /* + 运行在客户端,当客户端远程调用此方法时,内部实现: + + 1. 创建该方法需要的输入型Parcel对象_data、输出型Parcel对象_reply和返回值对象List + 2. 将该方法的参数信息写入_data中(如果有) + 3. 调用transact方法发起RPC请求,BinderProxy跨进程,同时挂起当前线程 + 4. 服务端的onTransact方法被调用 + 5. 直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果 + 6. 返回_reply中的数据 + */ + @Override + public List getBookList() throws RemoteException { + LogUtil.d(TAG_BINDER, "BookManagerImpl#Proxy#getBookList: " + Thread.currentThread().getId() + ", " + Process.myPid()); + + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + java.util.List _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(TRANSACTION_getBookList, _data, _reply, 0); + _reply.readException(); + _result = _reply.createTypedArrayList(Book.CREATOR); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + /* + addBook没有返回值,所以不需要从_reply中取出返回值 + */ + @Override + public void addBook(Book book) throws RemoteException { + LogUtil.d(TAG_BINDER, "BookManagerImpl#Proxy#addBook: " + Thread.currentThread().getId() + ", " + Process.myPid()); + + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + if ((book != null)) { + _data.writeInt(1); + book.writeToParcel(_data, 0); + } else { + _data.writeInt(0); + } + mRemote.transact(TRANSACTION_addBook, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } + + } + +} diff --git a/someApplications/multiprocess/src/main/res/drawable-v24/ic_launcher_foreground.xml b/someApplications/multiprocess/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/someApplications/multiprocess/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/res/drawable/ic_launcher_background.xml b/someApplications/multiprocess/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/someApplications/multiprocess/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/someApplications/multiprocess/src/main/res/layout/activity_main.xml b/someApplications/multiprocess/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..537afa9 --- /dev/null +++ b/someApplications/multiprocess/src/main/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/someApplications/multiprocess/src/main/res/layout/activity_second.xml b/someApplications/multiprocess/src/main/res/layout/activity_second.xml new file mode 100644 index 0000000..acbe511 --- /dev/null +++ b/someApplications/multiprocess/src/main/res/layout/activity_second.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/someApplications/multiprocess/src/main/res/layout/activity_third.xml b/someApplications/multiprocess/src/main/res/layout/activity_third.xml new file mode 100644 index 0000000..123be7c --- /dev/null +++ b/someApplications/multiprocess/src/main/res/layout/activity_third.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/someApplications/multiprocess/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher.png b/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher_round.png b/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher.png b/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher_round.png b/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher.png b/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher.png b/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/someApplications/multiprocess/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/someApplications/multiprocess/src/main/res/values/colors.xml b/someApplications/multiprocess/src/main/res/values/colors.xml new file mode 100644 index 0000000..f90f2fb --- /dev/null +++ b/someApplications/multiprocess/src/main/res/values/colors.xml @@ -0,0 +1,14 @@ + + + #3F51B5 + #303F9F + #FF4081 + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/res/values/strings.xml b/someApplications/multiprocess/src/main/res/values/strings.xml new file mode 100644 index 0000000..792145b --- /dev/null +++ b/someApplications/multiprocess/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + MultiProcess + \ No newline at end of file diff --git a/someApplications/multiprocess/src/main/res/values/styles.xml b/someApplications/multiprocess/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/someApplications/multiprocess/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/someApplications/multiprocess/src/test/java/com/baiiu/multiprocess/ExampleUnitTest.java b/someApplications/multiprocess/src/test/java/com/baiiu/multiprocess/ExampleUnitTest.java new file mode 100644 index 0000000..942b113 --- /dev/null +++ b/someApplications/multiprocess/src/test/java/com/baiiu/multiprocess/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.baiiu.multiprocess; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file