├── .gitignore ├── .idea ├── .name ├── codeStyles │ └── Project.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── render.experimental.xml ├── runConfigurations.xml └── vcs.xml ├── Android_PS3_Manager.apk ├── App_Info.jpg ├── Console_IDs.jpg ├── Memory.jpg ├── Misc.jpg ├── README.md ├── System.jpg ├── app ├── .gitignore ├── build.gradle ├── libs │ └── PS3MAPI.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── jprsd │ │ └── androidps3manager │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── jprsd │ │ │ └── androidps3manager │ │ │ ├── ManagerActivity.java │ │ │ ├── generics │ │ │ └── ManagerFragment.java │ │ │ └── ui │ │ │ ├── identification │ │ │ └── IdentificationFragment.java │ │ │ ├── memory │ │ │ ├── MemoryFragment.java │ │ │ └── MemoryViewModel.java │ │ │ ├── misc │ │ │ └── MiscFragment.java │ │ │ └── system │ │ │ ├── SystemFragment.java │ │ │ └── SystemViewModel.java │ └── res │ │ ├── color │ │ └── radio_buton_color.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── baseline_fingerprint_24.xml │ │ ├── baseline_memory_24.xml │ │ ├── baseline_miscellaneous_services_24.xml │ │ ├── baseline_online_prediction_24.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_ids.xml │ │ ├── fragment_memory.xml │ │ ├── fragment_misc.xml │ │ └── fragment_system.xml │ │ ├── menu │ │ ├── app_menu.xml │ │ └── bottom_nav_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── jprsd │ └── androidps3manager │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Android PS3 Manager -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/render.experimental.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Android_PS3_Manager.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/Android_PS3_Manager.apk -------------------------------------------------------------------------------- /App_Info.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/App_Info.jpg -------------------------------------------------------------------------------- /Console_IDs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/Console_IDs.jpg -------------------------------------------------------------------------------- /Memory.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/Memory.jpg -------------------------------------------------------------------------------- /Misc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/Misc.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-PS3-Manager 2 |

Control and real-time-mod your PS3HEN/CEX/DEX console with your Android device!

3 |

Download and install the provided .apk app file.

4 |

Powered by the PS3 Manager Java API.

5 |

Your PS3 must have WebMAN MOD installed for this app to work.

6 |

7 | System screen 8 | Memory screen 9 | Console IDs screen 10 |

11 |

12 | Miscellaneous screen 13 | Console IDs screen 14 |

15 | -------------------------------------------------------------------------------- /System.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/System.jpg -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | buildToolsVersion "30.0.1" 6 | 7 | compileOptions { 8 | sourceCompatibility JavaVersion.VERSION_1_8 9 | targetCompatibility JavaVersion.VERSION_1_8 10 | } 11 | 12 | defaultConfig { 13 | applicationId "com.jprsd.androidps3manager" 14 | minSdkVersion 24 15 | targetSdkVersion 30 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(dir: "libs", include: ["*.jar"]) 32 | implementation 'androidx.appcompat:appcompat:1.1.0' 33 | implementation 'com.google.android.material:material:1.1.0' 34 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 35 | implementation 'androidx.navigation:navigation-fragment:2.3.0' 36 | implementation 'androidx.navigation:navigation-ui:2.3.0' 37 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 38 | implementation files('libs/PS3MAPI.jar') 39 | testImplementation 'junit:junit:4.13' 40 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 41 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 42 | 43 | } -------------------------------------------------------------------------------- /app/libs/PS3MAPI.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprsd/Android-PS3-Manager/e19c69727ccc8a226b239cb555b4ff8e10085c85/app/libs/PS3MAPI.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/jprsd/androidps3manager/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.jprsd.androidps3manager; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.jprsd.androidps3manager", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ManagerActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager; 7 | 8 | import android.content.DialogInterface; 9 | import android.os.Bundle; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.appcompat.app.AlertDialog; 15 | import androidx.appcompat.app.AppCompatActivity; 16 | import androidx.fragment.app.Fragment; 17 | import androidx.fragment.app.FragmentManager; 18 | 19 | import com.google.android.material.bottomnavigation.BottomNavigationView; 20 | import com.jprsd.androidps3manager.ui.identification.IdentificationFragment; 21 | import com.jprsd.androidps3manager.ui.memory.MemoryFragment; 22 | import com.jprsd.androidps3manager.ui.misc.MiscFragment; 23 | import com.jprsd.androidps3manager.ui.system.SystemFragment; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 29 | 30 | /** 31 | * The main activity for this application 32 | */ 33 | public class ManagerActivity extends AppCompatActivity { 34 | 35 | /** PS3 Manager object */ 36 | private final PS3MAPI PS3 = new PS3MAPI(); 37 | 38 | /** Fragment manager for dealing with app navigation */ 39 | private final FragmentManager fragmentManager = getSupportFragmentManager(); 40 | 41 | /** Main system settings screen */ 42 | private final Fragment systemFragment = new SystemFragment(); 43 | /** Memory settings screen */ 44 | private final Fragment memoryFragment = new MemoryFragment(); 45 | /** Console ID settings screen */ 46 | private final Fragment idFragment = new IdentificationFragment(); 47 | /** Miscellaneous settings screen */ 48 | private final Fragment miscFragment = new MiscFragment(); 49 | 50 | /** The active fragment */ 51 | private Fragment visibleFragment; 52 | 53 | /** Tracks dialogs for dismissal to avoid memory leaks */ 54 | private final List dialogs = new ArrayList<>(); 55 | 56 | /** 57 | * Activity initialization 58 | * @param savedInstanceState Any previously saved data 59 | */ 60 | @Override 61 | protected void onCreate(Bundle savedInstanceState) { 62 | super.onCreate(savedInstanceState); 63 | setContentView(R.layout.activity_main); 64 | 65 | fragmentManager.beginTransaction() 66 | .add(R.id.fragmentPlaceholder, miscFragment).hide(miscFragment).commit(); 67 | fragmentManager.beginTransaction() 68 | .add(R.id.fragmentPlaceholder, idFragment).hide(idFragment).commit(); 69 | fragmentManager.beginTransaction() 70 | .add(R.id.fragmentPlaceholder, memoryFragment).hide(memoryFragment).commit(); 71 | 72 | fragmentManager.beginTransaction().add(R.id.fragmentPlaceholder, systemFragment).commit(); 73 | visibleFragment = systemFragment; 74 | 75 | BottomNavigationView navView = findViewById(R.id.nav_view); 76 | navView.setOnNavigationItemSelectedListener(item -> { 77 | switch (item.getItemId()) { 78 | case R.id.navigation_system: 79 | fragmentManager.beginTransaction() 80 | .hide(visibleFragment).show(systemFragment).commit(); 81 | visibleFragment = systemFragment; 82 | return true; 83 | case R.id.navigation_memory: 84 | fragmentManager.beginTransaction() 85 | .hide(visibleFragment).show(memoryFragment).commit(); 86 | visibleFragment = memoryFragment; 87 | return true; 88 | case R.id.navigation_ids: 89 | fragmentManager.beginTransaction() 90 | .hide(visibleFragment).show(idFragment).commit(); 91 | visibleFragment = idFragment; 92 | return true; 93 | case R.id.navigation_misc: 94 | fragmentManager.beginTransaction() 95 | .hide(visibleFragment).show(miscFragment).commit(); 96 | visibleFragment = miscFragment; 97 | return true; 98 | } 99 | return false; 100 | }); 101 | } 102 | 103 | /** 104 | * Activity destruction 105 | */ 106 | @Override 107 | protected void onDestroy() { 108 | for (AlertDialog dialog : dialogs) { 109 | if (dialog != null && dialog.isShowing()) { 110 | dialog.dismiss(); 111 | } 112 | } 113 | super.onDestroy(); 114 | } 115 | 116 | /** 117 | * Inflates app menu 118 | * @param menu The menu 119 | * @return true if successful 120 | */ 121 | @Override 122 | public boolean onCreateOptionsMenu(Menu menu) { 123 | getMenuInflater().inflate(R.menu.app_menu, menu); 124 | return true; 125 | } 126 | 127 | /** 128 | * Menu item selection handler 129 | * @param item The item that was selected 130 | * @return true if the event was handled 131 | */ 132 | @Override 133 | public boolean onOptionsItemSelected(@NonNull MenuItem item) { 134 | if (item.getItemId() == R.id.aboutMenuItem) { 135 | onAbout(); 136 | return true; 137 | } 138 | return false; 139 | } 140 | 141 | /** 142 | * Gets the PS3MAPI object 143 | * @return PS3 144 | */ 145 | public PS3MAPI getPS3() { 146 | return PS3; 147 | } 148 | 149 | /** 150 | * Displays the application info dialog 151 | */ 152 | private void onAbout() { 153 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 154 | builder.setTitle(R.string.app_name); 155 | builder.setMessage(R.string.message_about); 156 | 157 | final AlertDialog aboutDialog = builder.create(); 158 | dialogs.add(aboutDialog); 159 | aboutDialog.setButton(DialogInterface.BUTTON_POSITIVE, 160 | getResources().getText(android.R.string.ok), (dialogInterface, i) -> { 161 | dialogs.remove(aboutDialog); 162 | aboutDialog.dismiss(); 163 | }); 164 | aboutDialog.show(); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/generics/ManagerFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.generics; 7 | 8 | import android.os.Handler; 9 | import android.os.Looper; 10 | 11 | import androidx.fragment.app.Fragment; 12 | 13 | import com.jprsd.androidps3manager.ManagerActivity; 14 | 15 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 16 | 17 | /** 18 | * Common generic class for all fragments used in this app 19 | */ 20 | public abstract class ManagerFragment extends Fragment { 21 | 22 | /** 23 | * Handler for posting UI updates in background threads 24 | */ 25 | protected final Handler handler = new Handler(Looper.getMainLooper()); 26 | 27 | /** 28 | * Gets the PS3MAPI object from the main activity 29 | * @return PS3 30 | */ 31 | protected final PS3MAPI PS3() { 32 | return ((ManagerActivity) requireActivity()).getPS3(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/identification/IdentificationFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.identification; 7 | 8 | import android.content.Context; 9 | import android.os.Bundle; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.Button; 14 | import android.widget.EditText; 15 | import android.widget.Toast; 16 | 17 | import androidx.annotation.NonNull; 18 | import androidx.lifecycle.ViewModelProvider; 19 | 20 | import com.jprsd.androidps3manager.R; 21 | import com.jprsd.androidps3manager.generics.ManagerFragment; 22 | import com.jprsd.androidps3manager.ui.system.SystemViewModel; 23 | 24 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 25 | 26 | /** 27 | * Fragment for the console IDs section of the app 28 | */ 29 | public class IdentificationFragment extends ManagerFragment { 30 | 31 | /** 32 | * Initializer 33 | * @param inflater Inflater for developing the layout as specified in the XML 34 | * @param container The layout group this fragment is housed in 35 | * @param savedInstanceState Any previously saved data 36 | * @return The fragment root view 37 | */ 38 | @Override 39 | public View onCreateView(@NonNull LayoutInflater inflater, 40 | ViewGroup container, Bundle savedInstanceState) { 41 | SystemViewModel systemViewModel = 42 | new ViewModelProvider(requireActivity()).get(SystemViewModel.class); 43 | View root = inflater.inflate(R.layout.fragment_ids, container, false); 44 | 45 | final EditText idpsText = root.findViewById(R.id.idpsText); 46 | final EditText psidText = root.findViewById(R.id.psidText); 47 | final Button setIdButton = root.findViewById(R.id.setIdButton); 48 | 49 | systemViewModel.isConnected().observe(getViewLifecycleOwner(), connected -> { 50 | if (connected != null && connected) { 51 | setIdButton.setEnabled(true); 52 | } 53 | else { 54 | setIdButton.setEnabled(false); 55 | } 56 | }); 57 | setIdButton.setOnClickListener(view -> 58 | onSetIdpsAndPsid(idpsText.getText().toString().trim(), 59 | psidText.getText().toString().trim())); 60 | return root; 61 | } 62 | 63 | /** 64 | * Button handler for setting console IDs 65 | * @param idps New IDPS string 66 | * @param psid New PSID string 67 | */ 68 | private void onSetIdpsAndPsid(final String idps, final String psid) { 69 | final Context context = getContext(); 70 | if (idps.length() != 32 || psid.length() != 32) { 71 | Toast.makeText(context, R.string.invalid_ids, Toast.LENGTH_SHORT).show(); 72 | } 73 | else { 74 | final PS3MAPI PS3 = PS3(); 75 | new Thread() { 76 | @Override 77 | public void run() { 78 | if (PS3.setIdpsAndPsid(idps.substring(0, 15), idps.substring(16), 79 | psid.substring(0, 15), psid.substring(16))) { 80 | handler.post(() -> Toast.makeText(context, 81 | R.string.success_id_set, Toast.LENGTH_SHORT).show()); 82 | } 83 | else { 84 | handler.post(() -> Toast.makeText(context, 85 | R.string.failed_set_ids, Toast.LENGTH_SHORT).show()); 86 | } 87 | } 88 | }.start(); 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/memory/MemoryFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.memory; 7 | 8 | import android.annotation.SuppressLint; 9 | import android.content.Context; 10 | import android.os.Bundle; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.Button; 15 | import android.widget.EditText; 16 | import android.widget.TextView; 17 | import android.widget.Toast; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.lifecycle.ViewModelProvider; 21 | 22 | import com.jprsd.androidps3manager.R; 23 | import com.jprsd.androidps3manager.generics.ManagerFragment; 24 | import com.jprsd.androidps3manager.ui.system.SystemViewModel; 25 | 26 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 27 | 28 | /** 29 | * Fragment for the PS3 memory management section of the app 30 | */ 31 | public class MemoryFragment extends ManagerFragment { 32 | 33 | /** 34 | * View model for live data and UI changes in this fragment 35 | */ 36 | private MemoryViewModel memoryViewModel; 37 | 38 | /** 39 | * Initializer 40 | * @param inflater Inflater for developing the layout as specified in the XML 41 | * @param container The layout group this fragment is housed in 42 | * @param savedInstanceState Any previously saved data 43 | * @return The fragment root view 44 | */ 45 | @SuppressLint("SetTextI18n") 46 | @Override 47 | public View onCreateView(@NonNull LayoutInflater inflater, 48 | ViewGroup container, Bundle savedInstanceState) { 49 | SystemViewModel systemViewModel = 50 | new ViewModelProvider(requireActivity()).get(SystemViewModel.class); 51 | memoryViewModel = new ViewModelProvider(this).get(MemoryViewModel.class); 52 | View root = inflater.inflate(R.layout.fragment_memory, container, false); 53 | 54 | final TextView processIdText = root.findViewById(R.id.processIdText); 55 | final Button attachButton = root.findViewById(R.id.attachButton); 56 | final EditText memAddressGetText = root.findViewById(R.id.memAddressGetText); 57 | final EditText bytesNumText = root.findViewById(R.id.bytesNumText); 58 | final Button readMemoryButton = root.findViewById(R.id.readMemoryButton); 59 | final TextView memoryOutputText = root.findViewById(R.id.memoryOutputText); 60 | final EditText memAddressSetText = root.findViewById(R.id.memAddressSetText); 61 | final EditText memValueSetText = root.findViewById(R.id.memValueSetText); 62 | final Button writeMemoryButton = root.findViewById(R.id.writeMemoryButton); 63 | 64 | systemViewModel.isConnected().observe(getViewLifecycleOwner(), connected -> { 65 | if (connected != null && connected) { 66 | attachButton.setEnabled(true); 67 | } 68 | else { 69 | attachButton.setEnabled(false); 70 | memoryViewModel.setAttached(false); 71 | } 72 | }); 73 | memoryViewModel.isAttached().observe(getViewLifecycleOwner(), attached -> { 74 | if (attached != null && attached) { 75 | attachButton.setEnabled(false); 76 | processIdText.setText(Long.toString(PS3().getProcessId())); 77 | readMemoryButton.setEnabled(true); 78 | writeMemoryButton.setEnabled(true); 79 | } 80 | else { 81 | attachButton.setEnabled(true); 82 | processIdText.setText(getResources().getText(R.string.not_attached)); 83 | readMemoryButton.setEnabled(false); 84 | writeMemoryButton.setEnabled(false); 85 | } 86 | }); 87 | 88 | attachButton.setOnClickListener(view -> onAttach()); 89 | readMemoryButton.setOnClickListener(view -> { 90 | String numBytesString = bytesNumText.getText().toString().trim(); 91 | if (numBytesString.equals("")) { 92 | numBytesString = "1"; 93 | } 94 | else { 95 | for (int i = 0; i < numBytesString.length(); i++) { 96 | if (!Character.isDigit(numBytesString.charAt(i))) { 97 | numBytesString = "1"; 98 | break; 99 | } 100 | } 101 | } 102 | onReadMemory(memAddressGetText.getText().toString().trim(), 103 | Integer.parseInt(numBytesString), 104 | memoryOutputText); 105 | }); 106 | writeMemoryButton.setOnClickListener(view -> 107 | onWriteMemory(memAddressSetText.getText().toString().trim(), 108 | memValueSetText.getText().toString().trim())); 109 | 110 | return root; 111 | } 112 | 113 | /** 114 | * Attach button handler 115 | */ 116 | private void onAttach() { 117 | final PS3MAPI PS3 = PS3(); 118 | final Context context = getContext(); 119 | Toast.makeText(context, R.string.attaching, Toast.LENGTH_SHORT).show(); 120 | new Thread() { 121 | @Override 122 | public void run() { 123 | if (PS3.attach()) { 124 | handler.post(() -> Toast.makeText(context, 125 | R.string.attached, Toast.LENGTH_SHORT).show()); 126 | handler.post(() -> memoryViewModel.setAttached(true)); 127 | } 128 | else { 129 | handler.post(() -> Toast.makeText(context, 130 | R.string.attaching_failed, Toast.LENGTH_SHORT).show()); 131 | } 132 | } 133 | }.start(); 134 | } 135 | 136 | /** 137 | * Button handler for reading PS3 memory 138 | * @param address PS3 memory address 139 | * @param length Number of bytes to read 140 | * @param output The TextView to be updated with the address values 141 | */ 142 | private void onReadMemory(String address, final int length, final TextView output) { 143 | final PS3MAPI PS3 = PS3(); 144 | final Context context = getContext(); 145 | final String addressTrimmed = trimHex(address); 146 | new Thread() { 147 | @Override 148 | public void run() { 149 | String[] result = new String[1]; 150 | if (PS3.getMemory(addressTrimmed, length, result)) { 151 | handler.post(() -> output.setText(result[0])); 152 | } 153 | else { 154 | handler.post(() -> Toast.makeText(context, 155 | R.string.read_mem_fail, Toast.LENGTH_SHORT).show()); 156 | } 157 | } 158 | }.start(); 159 | } 160 | 161 | /** 162 | * Button handler for writing memory to the PS3 163 | * @param address PS3 memory address 164 | * @param value Hex value 165 | */ 166 | private void onWriteMemory(String address, final String value) { 167 | final PS3MAPI PS3 = PS3(); 168 | final Context context = getContext(); 169 | final String addressTrimmed = trimHex(address); 170 | new Thread() { 171 | @Override 172 | public void run() { 173 | if (PS3.setMemory(addressTrimmed, value)) { 174 | handler.post(() -> Toast.makeText(context, 175 | R.string.write_mem_success, Toast.LENGTH_SHORT).show()); 176 | } 177 | else { 178 | handler.post(() -> Toast.makeText(context, 179 | R.string.write_mem_fail, Toast.LENGTH_SHORT).show()); 180 | } 181 | } 182 | }.start(); 183 | } 184 | 185 | /** 186 | * Removes the 0x prefix on memory address strings if present 187 | * @param string The hex string to trim 188 | * @return The trimmed string 189 | */ 190 | private String trimHex(String string) { 191 | if (string.length() > 2 && string.toLowerCase().contains("0x")) { 192 | return string.substring(2); 193 | } 194 | return string; 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/memory/MemoryViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.memory; 7 | 8 | import androidx.lifecycle.LiveData; 9 | import androidx.lifecycle.MutableLiveData; 10 | import androidx.lifecycle.ViewModel; 11 | 12 | /** 13 | * View model for live data and UI changes in the app's memory fragment 14 | */ 15 | public class MemoryViewModel extends ViewModel { 16 | 17 | /** 18 | * Observable boolean value for the process-attached state 19 | */ 20 | private MutableLiveData attached; 21 | 22 | /** 23 | * Default constructor 24 | */ 25 | public MemoryViewModel() { 26 | attached = new MutableLiveData<>(); 27 | attached.setValue(false); 28 | } 29 | 30 | /** 31 | * Gets the observable attachment state 32 | * @return Boolean live data 33 | */ 34 | public LiveData isAttached() { 35 | return attached; 36 | } 37 | 38 | /** 39 | * Updates the attachment state and notifies observers of changes 40 | * @param attached The new state 41 | */ 42 | public void setAttached(boolean attached) { 43 | this.attached.setValue(attached); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/misc/MiscFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.misc; 7 | 8 | import android.content.Context; 9 | import android.os.Bundle; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.Button; 14 | import android.widget.EditText; 15 | import android.widget.RadioButton; 16 | import android.widget.RadioGroup; 17 | import android.widget.Toast; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.lifecycle.ViewModelProvider; 21 | 22 | import com.jprsd.androidps3manager.R; 23 | import com.jprsd.androidps3manager.generics.ManagerFragment; 24 | import com.jprsd.androidps3manager.ui.system.SystemViewModel; 25 | 26 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 27 | 28 | /** 29 | * Fragment for the miscellaneous section of the app 30 | */ 31 | public class MiscFragment extends ManagerFragment { 32 | 33 | /** 34 | * Initializer 35 | * @param inflater Inflater for developing the layout as specified in the XML 36 | * @param container The layout group this fragment is housed in 37 | * @param savedInstanceState Any previously saved data 38 | * @return The fragment root view 39 | */ 40 | @Override 41 | public View onCreateView(@NonNull LayoutInflater inflater, 42 | ViewGroup container, Bundle savedInstanceState) { 43 | SystemViewModel systemViewModel = 44 | new ViewModelProvider(requireActivity()).get(SystemViewModel.class); 45 | View root = inflater.inflate(R.layout.fragment_misc, container, false); 46 | 47 | final EditText notifyText = root.findViewById(R.id.notifyText); 48 | final Button notifyButton = root.findViewById(R.id.notifyButton); 49 | 50 | final Button singleRingButton = root.findViewById(R.id.singleRingButton); 51 | final Button doubleRingButton = root.findViewById(R.id.doubleRingButton); 52 | final Button tripleRingButton = root.findViewById(R.id.tripleRingButton); 53 | 54 | final RadioGroup lightColorRadioGroup = root.findViewById(R.id.lightColorRadioGroup); 55 | final RadioButton redRadioButton = root.findViewById(R.id.redRadioButton); 56 | final RadioButton greenRadioButton = root.findViewById(R.id.greenRadioButton); 57 | final RadioButton yellowRadioButton = root.findViewById(R.id.yellowRadioButton); 58 | 59 | final RadioGroup lightModeRadioGroup = root.findViewById(R.id.lightModeRadioGroup); 60 | final RadioButton offRadioButton = root.findViewById(R.id.offRadioButton); 61 | final RadioButton onRadioButton = root.findViewById(R.id.onRadioButton); 62 | final RadioButton blinkFastRadioButton = root.findViewById(R.id.blinkFastRadioButton); 63 | final RadioButton blinkSlowRadioButton = root.findViewById(R.id.blinkSlowButton); 64 | 65 | final Button lightSetButton = root.findViewById(R.id.lightSetButton); 66 | 67 | systemViewModel.isConnected().observe(getViewLifecycleOwner(), connected -> { 68 | if (connected != null && connected) { 69 | notifyButton.setEnabled(true); 70 | singleRingButton.setEnabled(true); 71 | doubleRingButton.setEnabled(true); 72 | tripleRingButton.setEnabled(true); 73 | redRadioButton.setEnabled(true); 74 | greenRadioButton.setEnabled(true); 75 | yellowRadioButton.setEnabled(true); 76 | offRadioButton.setEnabled(true); 77 | onRadioButton.setEnabled(true); 78 | blinkFastRadioButton.setEnabled(true); 79 | blinkSlowRadioButton.setEnabled(true); 80 | lightSetButton.setEnabled(true); 81 | } 82 | else { 83 | notifyButton.setEnabled(false); 84 | singleRingButton.setEnabled(false); 85 | doubleRingButton.setEnabled(false); 86 | tripleRingButton.setEnabled(false); 87 | redRadioButton.setEnabled(false); 88 | greenRadioButton.setEnabled(false); 89 | yellowRadioButton.setEnabled(false); 90 | offRadioButton.setEnabled(false); 91 | onRadioButton.setEnabled(false); 92 | blinkFastRadioButton.setEnabled(false); 93 | blinkSlowRadioButton.setEnabled(false); 94 | lightSetButton.setEnabled(false); 95 | } 96 | }); 97 | 98 | notifyButton.setOnClickListener(view -> onNotify(notifyText.getText().toString().trim())); 99 | singleRingButton.setOnClickListener(view -> onRingBuzzer(PS3MAPI.PS3Buzzer.Mode.SINGLE)); 100 | doubleRingButton.setOnClickListener(view -> onRingBuzzer(PS3MAPI.PS3Buzzer.Mode.DOUBLE)); 101 | tripleRingButton.setOnClickListener(view -> onRingBuzzer(PS3MAPI.PS3Buzzer.Mode.TRIPLE)); 102 | 103 | lightSetButton.setOnClickListener(view -> { 104 | PS3MAPI.PS3Light.Color color; 105 | switch (lightColorRadioGroup.getCheckedRadioButtonId()) { 106 | case R.id.redRadioButton: 107 | color = PS3MAPI.PS3Light.Color.RED; 108 | break; 109 | case R.id.greenRadioButton: 110 | color = PS3MAPI.PS3Light.Color.GREEN; 111 | break; 112 | case R.id.yellowRadioButton: 113 | default: 114 | color = PS3MAPI.PS3Light.Color.YELLOW; 115 | break; 116 | } 117 | PS3MAPI.PS3Light.Mode mode; 118 | switch (lightModeRadioGroup.getCheckedRadioButtonId()) { 119 | case R.id.offRadioButton: 120 | mode = PS3MAPI.PS3Light.Mode.OFF; 121 | break; 122 | case R.id.onRadioButton: 123 | mode = PS3MAPI.PS3Light.Mode.ON; 124 | break; 125 | case R.id.blinkFastRadioButton: 126 | mode = PS3MAPI.PS3Light.Mode.BLINK_FAST; 127 | break; 128 | case R.id.blinkSlowButton: 129 | default: 130 | mode = PS3MAPI.PS3Light.Mode.BLINK_SLOW; 131 | break; 132 | } 133 | onSetLights(color, mode); 134 | }); 135 | 136 | return root; 137 | } 138 | 139 | /** 140 | * Button handler for sending PS3 message notifications 141 | * @param message The message to send 142 | */ 143 | private void onNotify(final String message) { 144 | final PS3MAPI PS3 = PS3(); 145 | final Context context = getContext(); 146 | new Thread() { 147 | @Override 148 | public void run() { 149 | if (!PS3.notify(message)) { 150 | handler.post(() -> Toast.makeText(context, 151 | R.string.notify_fail, Toast.LENGTH_SHORT).show()); 152 | } 153 | } 154 | }.start(); 155 | } 156 | 157 | /** 158 | * Button handler for ringing the PS3 buzzer 159 | * @param mode The buzzer mode 160 | */ 161 | private void onRingBuzzer(final PS3MAPI.PS3Buzzer.Mode mode) { 162 | final PS3MAPI PS3 = PS3(); 163 | final Context context = getContext(); 164 | new Thread() { 165 | @Override 166 | public void run() { 167 | if (!PS3.ringBuzzer(mode)) { 168 | handler.post(() -> Toast.makeText(context, 169 | R.string.buzzer_fail, Toast.LENGTH_SHORT).show()); 170 | } 171 | } 172 | }.start(); 173 | } 174 | 175 | /** 176 | * Button handler for adjusting the PS3 LEDs 177 | * @param color The light color 178 | * @param mode The light mode 179 | */ 180 | private void onSetLights(final PS3MAPI.PS3Light.Color color, final PS3MAPI.PS3Light.Mode mode) { 181 | final PS3MAPI PS3 = PS3(); 182 | final Context context = getContext(); 183 | new Thread() { 184 | @Override 185 | public void run() { 186 | if (!PS3.setLights(color, mode)) { 187 | handler.post(() -> Toast.makeText(context, 188 | R.string.lights_fail, Toast.LENGTH_SHORT).show()); 189 | } 190 | } 191 | }.start(); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/system/SystemFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.system; 7 | 8 | import android.content.Context; 9 | import android.os.Bundle; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.Button; 14 | import android.widget.EditText; 15 | import android.widget.RadioButton; 16 | import android.widget.RadioGroup; 17 | import android.widget.Toast; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.lifecycle.ViewModelProvider; 21 | 22 | import com.jprsd.androidps3manager.R; 23 | import com.jprsd.androidps3manager.generics.ManagerFragment; 24 | 25 | import ps3.mods.jprsd.ps3mapi.PS3MAPI; 26 | 27 | /** 28 | * Fragment for the main system settings section of the app 29 | */ 30 | public class SystemFragment extends ManagerFragment { 31 | 32 | /** 33 | * View model for live data and UI changes in this fragment 34 | */ 35 | private SystemViewModel systemViewModel; 36 | 37 | /** 38 | * Initializer 39 | * @param inflater Inflater for developing the layout as specified in the XML 40 | * @param container The layout group this fragment is housed in 41 | * @param savedInstanceState Any previously saved data 42 | * @return The fragment root view 43 | */ 44 | @Override 45 | public View onCreateView(@NonNull LayoutInflater inflater, 46 | ViewGroup container, Bundle savedInstanceState) { 47 | systemViewModel = new ViewModelProvider(requireActivity()).get(SystemViewModel.class); 48 | View root = inflater.inflate(R.layout.fragment_system, container, false); 49 | 50 | final EditText ipAddressText = root.findViewById(R.id.ipAddressText); 51 | final Button connectButton = root.findViewById(R.id.connectButton); 52 | final Button disconnectButton = root.findViewById(R.id.disconnectButton); 53 | final RadioGroup powerRadioGroup = root.findViewById(R.id.powerRadioGroup); 54 | final RadioButton shutdownRadio = root.findViewById(R.id.shutdownButton); 55 | final RadioButton rebootRadio = root.findViewById(R.id.rebootButton); 56 | final Button powerExecuteButton = root.findViewById(R.id.powerExecuteButton); 57 | 58 | systemViewModel.isConnected().observe(getViewLifecycleOwner(), connected -> { 59 | if (connected != null && connected) { 60 | ipAddressText.setEnabled(false); 61 | connectButton.setEnabled(false); 62 | shutdownRadio.setEnabled(true); 63 | rebootRadio.setEnabled(true); 64 | powerExecuteButton.setEnabled(true); 65 | } 66 | else { 67 | ipAddressText.setEnabled(true); 68 | connectButton.setEnabled(true); 69 | shutdownRadio.setEnabled(false); 70 | rebootRadio.setEnabled(false); 71 | powerExecuteButton.setEnabled(false); 72 | } 73 | }); 74 | 75 | connectButton.setOnClickListener(view -> 76 | onConnect(ipAddressText.getText().toString().trim())); 77 | disconnectButton.setOnClickListener(view -> onDisconnect()); 78 | powerExecuteButton.setOnClickListener(view -> 79 | onPowerExecute(powerRadioGroup.getCheckedRadioButtonId())); 80 | 81 | return root; 82 | } 83 | 84 | /** 85 | * Button handler for connecting to the PS3 86 | * @param ipAddress The PS3 IP address 87 | */ 88 | private void onConnect(String ipAddress) { 89 | final PS3MAPI PS3 = PS3(); 90 | final Context context = getContext(); 91 | 92 | try { 93 | PS3.setIpAddress(ipAddress); 94 | } catch (Exception e) { 95 | Toast.makeText(context, R.string.invalid_ip, Toast.LENGTH_SHORT).show(); 96 | return; 97 | } 98 | 99 | Toast.makeText(context, R.string.connecting, Toast.LENGTH_SHORT).show(); 100 | new Thread() { 101 | @Override 102 | public void run() { 103 | if (PS3.connect()) { 104 | handler.post(() -> systemViewModel.setConnected(true)); 105 | handler.post(() -> Toast.makeText(context, 106 | R.string.connected, Toast.LENGTH_SHORT).show()); 107 | } 108 | else { 109 | handler.post(() -> Toast.makeText(context, 110 | R.string.connection_failed, Toast.LENGTH_SHORT).show()); 111 | } 112 | } 113 | }.start(); 114 | } 115 | 116 | /** 117 | * Button handler for disconnecting from the PS3 118 | */ 119 | private void onDisconnect() { 120 | PS3().disconnect(); 121 | systemViewModel.setConnected(false); 122 | } 123 | 124 | /** 125 | * Button handler for system power settings 126 | * @param mode The selected power option 127 | */ 128 | private void onPowerExecute(int mode) { 129 | final PS3MAPI PS3 = PS3(); 130 | final Context context = getContext(); 131 | switch (mode) { 132 | case R.id.shutdownButton: 133 | new Thread() { 134 | @Override 135 | public void run() { 136 | if (PS3.shutdown()) { 137 | handler.post(() -> onDisconnect()); 138 | } 139 | else { 140 | handler.post(() -> Toast.makeText(context, 141 | R.string.shutdown_fail, Toast.LENGTH_SHORT).show()); 142 | } 143 | } 144 | }.start(); 145 | break; 146 | case R.id.rebootButton: 147 | default: 148 | new Thread() { 149 | @Override 150 | public void run() { 151 | if (PS3.reboot()) { 152 | handler.post(() -> onDisconnect()); 153 | } 154 | else { 155 | handler.post(() -> Toast.makeText(context, 156 | R.string.reboot_fail, Toast.LENGTH_SHORT).show()); 157 | } 158 | } 159 | }.start(); 160 | break; 161 | } 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /app/src/main/java/com/jprsd/androidps3manager/ui/system/SystemViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Jaideep Prasad 3 | * Date: 2020 4 | */ 5 | 6 | package com.jprsd.androidps3manager.ui.system; 7 | 8 | import androidx.lifecycle.LiveData; 9 | import androidx.lifecycle.MutableLiveData; 10 | import androidx.lifecycle.ViewModel; 11 | 12 | /** 13 | * View model for live data and UI changes in the app's system fragment 14 | */ 15 | public class SystemViewModel extends ViewModel { 16 | 17 | /** 18 | * Observable boolean value for the PS3 connection state 19 | */ 20 | private MutableLiveData connected; 21 | 22 | /** 23 | * Default constructor 24 | */ 25 | public SystemViewModel() { 26 | connected = new MutableLiveData<>(); 27 | connected.setValue(false); 28 | } 29 | 30 | /** 31 | * Gets the observable connection state 32 | * @return Boolean live data 33 | */ 34 | public LiveData isConnected() { 35 | return connected; 36 | } 37 | 38 | /** 39 | * Sets the connection state and notifies observers of changes 40 | * @param connected The new state 41 | */ 42 | public void setConnected(boolean connected) { 43 | this.connected.setValue(connected); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/res/color/radio_buton_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_fingerprint_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_memory_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_miscellaneous_services_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_online_prediction_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 16 | 17 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 17 | 18 | 29 | 30 | 40 | 41 | 53 | 54 | 65 | 66 | 78 | 79 |