diff --git a/.aiexclude b/.aiexclude new file mode 100644 index 0000000..a7ac424 --- /dev/null +++ b/.aiexclude @@ -0,0 +1,2 @@ +.git +app/src/main/res/raw/tests.xml diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130..b86273d 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml new file mode 100644 index 0000000..4ea72a9 --- /dev/null +++ b/.idea/copilot.data.migration.agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.edit.xml b/.idea/copilot.data.migration.edit.xml new file mode 100644 index 0000000..8648f94 --- /dev/null +++ b/.idea/copilot.data.migration.edit.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0897082..5ef3273 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,15 +4,15 @@ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c8f004d --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 2a179b3..f88435e 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + + - + diff --git a/.idea/modules.xml b/.idea/modules.xml index 12ac2f4..0da54eb 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,11 +2,7 @@ - - - - \ No newline at end of file diff --git a/.idea/modules/app/streaming-android.app.androidTest.iml b/.idea/modules/app/streaming-android.app.androidTest.iml deleted file mode 100644 index 167a11a..0000000 --- a/.idea/modules/app/streaming-android.app.androidTest.iml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules/app/streaming-android.app.iml b/.idea/modules/app/streaming-android.app.iml index e429359..33d010e 100644 --- a/.idea/modules/app/streaming-android.app.iml +++ b/.idea/modules/app/streaming-android.app.iml @@ -1,10 +1,10 @@ - + - @@ -13,19 +13,8 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules/app/streaming-android.app.main.iml b/.idea/modules/app/streaming-android.app.main.iml deleted file mode 100644 index d197b1e..0000000 --- a/.idea/modules/app/streaming-android.app.main.iml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules/app/streaming-android.app.unitTest.iml b/.idea/modules/app/streaming-android.app.unitTest.iml deleted file mode 100644 index f030b48..0000000 --- a/.idea/modules/app/streaming-android.app.unitTest.iml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/studiobot.xml b/.idea/studiobot.xml new file mode 100644 index 0000000..539e3b8 --- /dev/null +++ b/.idea/studiobot.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f210136..1e7fc7d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' + android { - compileSdkVersion 30 - buildToolsVersion '19.1.0' - defaultConfig { + compileSdkVersion 34 + defaultConfig { applicationId "red5pro.org.testandroidproject" minSdkVersion 26 - targetSdkVersion 30 + targetSdkVersion 34 versionCode 9000 versionName "10.9.0.0" } @@ -15,13 +15,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - lintOptions { - checkReleaseBuilds false - // Or, if you prefer, you can continue to check for errors in release builds, - // but continue the build even when errors are found: - abortOnError false - } -// productFlavors { + // productFlavors { // // armv7 { // ndk { @@ -36,10 +30,20 @@ android { //// } // // } - buildToolsVersion '28.0.3' - useLibrary 'org.apache.http.legacy' + useLibrary 'org.apache.http.legacy' + namespace 'red5pro.org.testandroidproject' + lint { + abortOnError false + checkReleaseBuilds false + } } dependencies { + + def fragment_version = "1.8.9" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.7.1' + implementation "androidx.fragment:fragment:$fragment_version" + implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'org.java-websocket:Java-WebSocket:1.5.2' implementation 'ch.qos.logback:logback-classic:1.2.3' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a51aad3..a4209bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,8 @@ - + - @@ -23,7 +21,7 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" > + android:theme="@style/AppTheme"> + android:windowSoftInputMode="adjustPan" + android:exported="true" + > @@ -45,9 +44,11 @@ diff --git a/app/src/main/java/red5pro/org/testandroidproject/TestDetailFragment.java b/app/src/main/java/red5pro/org/testandroidproject/TestDetailFragment.java index 05aa063..a90286a 100644 --- a/app/src/main/java/red5pro/org/testandroidproject/TestDetailFragment.java +++ b/app/src/main/java/red5pro/org/testandroidproject/TestDetailFragment.java @@ -1,4 +1,3 @@ -// // Copyright © 2015 Infrared5, Inc. All rights reserved. // // The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code") @@ -25,14 +24,13 @@ // package red5pro.org.testandroidproject; -import android.app.Activity; +import android.content.Context; import android.os.Bundle; -import android.app.Fragment; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import com.red5pro.streaming.R5Stream; import red5pro.org.testandroidproject.tests.TestContent; @@ -41,17 +39,15 @@ * A fragment representing a single Test detail screen. * This fragment is contained in a {@link TestListActivity} */ -public class TestDetailFragment extends Fragment { - /** - * The fragment argument representing the item ID that this fragment - * represents. - */ - public static final String ARG_ITEM_ID = "item_id"; - - /** - * The dummy content this fragment is presenting. - */ - private TestContent mItem; +public class TestDetailFragment extends Fragment { // Changed to androidx.fragment.app.Fragment + /** + * The fragment argument representing the item ID that this fragment + * represents. + */ + public static final String ARG_ITEM_ID = "item_id"; /** + * The dummy content this fragment is presenting. + */ + private TestContent mItem; // Consider if this is still needed or how it's initialized /** * A dummy implementation of the {@link TestListFragment.Callbacks} interface that does @@ -69,77 +65,78 @@ public void onAddConnectionParams() {} */ protected TestListFragment.Callbacks mCallbacks = sDummyCallbacks; - /** - * Mandatory empty constructor for the fragment manager to instantiate the - * fragment (e.g. upon screen orientation changes). - */ - public TestDetailFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (getArguments().containsKey(ARG_ITEM_ID)) { - // Load the dummy content specified by the fragment - // arguments. In a real-world scenario, use a Loader - // to load content from a content provider. - - - - //mItem = TestContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID)); - //Load the Actual test for this TestItem using the Class property of the XML file - + /** + * Mandatory empty constructor for the fragment manager to instantiate the + * fragment (e.g. upon screen orientation changes). + */ + public TestDetailFragment() { + } - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null && getArguments().containsKey(ARG_ITEM_ID)) { + // Load the dummy content specified by the fragment + // arguments. In a real-world scenario, use a Loader + // to load content from a content provider. - } + // mItem = TestContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID)); + // Load the Actual test for this TestItem using the Class property of the XML file + } + } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_test_detail, container, false); + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_test_detail, container, false); - // Show the dummy content as text in a TextView. + // Show the dummy content as text in a TextView. + // POPULATE THE VIEW!!! - //POPULATE THE VIEW!!! + return rootView; + } + public Boolean isPublisherTest () { + return false; + } - return rootView; - } + public Boolean shouldClean() { + return true; + } - public Boolean isPublisherTest () { - return false; - } - public Boolean shouldClean() { - return true; - } - public R5Stream.RecordType getPublishRecordType () { - String type = TestContent.GetPropertyString("record_mode"); - if (type.equals("Record")) { - return R5Stream.RecordType.Record; - } else if (type.equals("Append")) { - return R5Stream.RecordType.Append; - } - return R5Stream.RecordType.Live; - } + public R5Stream.RecordType getPublishRecordType () { + // It's safer to use getArguments() to retrieve properties + // if they are passed during fragment creation. + // Assuming TestContent.GetPropertyString is a static helper that's still relevant. + String type = TestContent.GetPropertyString("record_mode"); + if ("Record".equals(type)) { // Use equals for string comparison + return R5Stream.RecordType.Record; + } else if ("Append".equals(type)) { + return R5Stream.RecordType.Append; + } + return R5Stream.RecordType.Live; + } - public void onAttach(Activity activity) { - super.onAttach(activity); + @Override + public void onAttach(Context context) { // Changed signature to use Context + super.onAttach(context); // Activities containing this fragment must implement its callbacks. - if (!(activity instanceof TestListFragment.Callbacks)) { - throw new IllegalStateException("Activity must implement fragment's callbacks."); + if (context instanceof TestListFragment.Callbacks) { + mCallbacks = (TestListFragment.Callbacks) context; + } else { + // Consider logging a warning or throwing an exception if the context + // is not guaranteed to implement the callbacks. + // For example, if this fragment can be hosted by different activities. + throw new IllegalStateException(context.toString() + + " must implement TestListFragment.Callbacks"); } - - mCallbacks = (TestListFragment.Callbacks) activity; } @Override public void onDetach() { super.onDetach(); - // Reset the active callbacks interface to the dummy implementation. mCallbacks = sDummyCallbacks; } diff --git a/app/src/main/java/red5pro/org/testandroidproject/TestListActivity.java b/app/src/main/java/red5pro/org/testandroidproject/TestListActivity.java index decb143..557b9c3 100644 --- a/app/src/main/java/red5pro/org/testandroidproject/TestListActivity.java +++ b/app/src/main/java/red5pro/org/testandroidproject/TestListActivity.java @@ -28,7 +28,11 @@ import android.Manifest; import android.annotation.TargetApi; import android.app.AlertDialog; -import android.app.Fragment; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + import android.content.Context; import android.content.DialogInterface; import android.content.res.Configuration; @@ -66,8 +70,8 @@ * {@link TestListFragment.Callbacks} interface * to listen for item selections. */ -public class TestListActivity extends Activity - implements TestListFragment.Callbacks, PublishTestListener, ActivityCompat.OnRequestPermissionsResultCallback { +public class TestListActivity extends AppCompatActivity + implements TestListFragment.Callbacks, PublishTestListener { /** * Whether or not the activity is in two-pane mode, i.e. running on a tablet @@ -76,70 +80,66 @@ public class TestListActivity extends Activity private boolean mTwoPane; private TestDetailFragment fragment = null; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_test_list); - - if (findViewById(R.id.test_detail_container) != null) { - // The detail container view will be present only in the - // large-screen layouts (res/values-large and - // res/values-sw600dp). If this view is present, then the - // activity should be in two-pane mode. - mTwoPane = true; - - // In two-pane mode, list items should be given the - // 'activated' state when touched. - ((TestListFragment) getFragmentManager() - .findFragmentById(R.id.test_list)) - .setActivateOnItemClick(true); - } - else { - TestListFragment frag = new TestListFragment(); - - getFragmentManager().beginTransaction() - .replace(R.id.test_list_container, frag) - .commit(); - } - - // TODO: If exposing deep links into your app, handle intents here. - - //onItemSelected("0"); - - } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_test_list); + + FragmentManager fm = getSupportFragmentManager(); // Use AndroidX FragmentManager + + if (findViewById(R.id.test_detail_container) != null) { + // The detail container view will be present only in the + // large-screen layouts (res/values-large and + // res/values-sw600dp). If this view is present, then the + // activity should be in two-pane mode. + mTwoPane = true; + + // In two-pane mode, list items should be given the + // 'activated' state when touched. + // Ensure TestListFragment is an androidx.fragment.app.Fragment + TestListFragment listFragment = (TestListFragment) fm.findFragmentById(R.id.test_list); + if (listFragment != null) { + listFragment.setActivateOnItemClick(true); + } + } else { + // Ensure TestListFragment is an androidx.fragment.app.Fragment + TestListFragment frag = new TestListFragment(); + fm.beginTransaction() + .replace(R.id.test_list_container, frag) + .commit(); + } - @Override - public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PermissionChecker.PERMISSION_GRANTED - || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PermissionChecker.PERMISSION_GRANTED - || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED) { - - getFragmentManager().beginTransaction().addToBackStack(null).commit(); - ActivityCompat.requestPermissions(this, - new String[]{ - android.Manifest.permission.CAMERA, - android.Manifest.permission.RECORD_AUDIO, - android.Manifest.permission.WRITE_EXTERNAL_STORAGE - }, 1337); - } - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PermissionChecker.PERMISSION_GRANTED + || ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PermissionChecker.PERMISSION_GRANTED + || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED) { + + fm.beginTransaction().addToBackStack(null).commit(); + ActivityCompat.requestPermissions(this, + new String[]{ + android.Manifest.permission.CAMERA, + android.Manifest.permission.RECORD_AUDIO, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE + }, 1337); + } + } - return super.onCreateView(parent, name, context, attrs); - } + } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {} + @Override + public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { + return super.onCreateView(parent, name, context, attrs); + } @Override - public void onAddConnectionParams () { + public void onAddConnectionParams() { try { - getFragmentManager().beginTransaction() - .replace(R.id.test_list_container, new ParamTable()) - .addToBackStack(null) - .commit(); -// mIsParamsFragmentActive = true; + // Ensure ParamTable is an androidx.fragment.app.Fragment + getSupportFragmentManager().beginTransaction() + .replace(R.id.test_list_container, new ParamTable()) + .addToBackStack(null) // This will add the transaction to the back stack + .setReorderingAllowed(true) // Recommended for optimal animations and transitions + .commit(); } catch (Exception e) { e.printStackTrace(); } @@ -149,49 +149,37 @@ public void onAddConnectionParams () { * Callback method from {@link TestListFragment.Callbacks} * indicating that the item with the given ID was selected. */ - @Override - public void onItemSelected(String id) { - + @Override + public void onItemSelected(String id) { + int _id = Integer.parseInt(id); + TestContent.SetTestItem(_id); - int _id = Integer.parseInt(id); + Bundle arguments = new Bundle(); + arguments.putString(TestDetailFragment.ARG_ITEM_ID, id); - TestContent.SetTestItem( _id ); + if (fragment != null) { + // onBackPressed(); // This might have unintended side effects if the back stack isn't what you expect. + } - Bundle arguments = new Bundle(); - arguments.putString(TestDetailFragment.ARG_ITEM_ID, id); + try { + String className = TestContent.ITEMS.get(_id).className; + Class testClass = Class.forName("red5pro.org.testandroidproject.tests." + className + "." + className); + fragment = (TestDetailFragment) testClass.getConstructors()[0].newInstance(); + } catch (Exception e) { + e.printStackTrace(); + fragment = new TestDetailFragment(); + } + fragment.setArguments(arguments); - if( fragment != null ) - onBackPressed(); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(mTwoPane ? R.id.test_detail_container : R.id.test_list_container, fragment); + transaction.addToBackStack(null); + transaction.setReorderingAllowed(true); + transaction.commit(); + } - try { - String className = TestContent.ITEMS.get( _id ).className; - Class testClass = Class.forName( "red5pro.org.testandroidproject.tests." + className + "." + className ); - fragment = (TestDetailFragment)testClass.getConstructors()[0].newInstance(); - } catch (Exception e) { - e.printStackTrace(); - fragment = new TestDetailFragment(); - } - fragment.setArguments(arguments); - - if (mTwoPane) { - // In two-pane mode, show the detail view in this activity by - // adding or replacing the detail fragment using a - // fragment transaction. - getFragmentManager().beginTransaction() - .replace(R.id.test_detail_container, fragment) - .addToBackStack(null) - .commit(); - - } else { - // In single-pane mode, replace the list with the fragment - getFragmentManager().beginTransaction() - .replace(R.id.test_list_container, fragment) - .addToBackStack(null) - .commit(); - } - } - @Override + @Override protected void onPause() { super.onPause(); @@ -258,14 +246,13 @@ public void onPublishFlushBufferComplete() { } } - @Override - public void onConfigurationChanged(Configuration config) { - Log.d("TestListActivity", "config changed."); - Fragment test = getFragmentManager().findFragmentByTag("test"); - if (test != null) { - test.onConfigurationChanged(config); - } - - super.onConfigurationChanged(config); - } + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { // Added @NonNull + super.onConfigurationChanged(newConfig); // Call super + Log.d("TestListActivity", "config changed."); + Fragment testFragment = getSupportFragmentManager().findFragmentByTag("test"); // "test" is the tag + if (testFragment != null) { + testFragment.onConfigurationChanged(newConfig); + } + } } diff --git a/app/src/main/java/red5pro/org/testandroidproject/TestListFragment.java b/app/src/main/java/red5pro/org/testandroidproject/TestListFragment.java index 2f4acf0..8e694b1 100644 --- a/app/src/main/java/red5pro/org/testandroidproject/TestListFragment.java +++ b/app/src/main/java/red5pro/org/testandroidproject/TestListFragment.java @@ -25,11 +25,16 @@ // package red5pro.org.testandroidproject; -import android.app.Activity; +import android.content.Context; import android.content.res.Resources; import android.os.Bundle; -import android.app.ListFragment; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; @@ -44,7 +49,7 @@ * Activities containing this fragment MUST implement the {@link Callbacks} * interface. */ -public class TestListFragment extends ListFragment { +public class TestListFragment extends Fragment { /** * The serialization (saved instance state) Bundle key representing the @@ -63,7 +68,10 @@ public class TestListFragment extends ListFragment { */ private int mActivatedPosition = ListView.INVALID_POSITION; - /** + private ListView mListView; + private ArrayAdapter mAdapter; + + /** * A callback interface that all activities containing this fragment must * implement. This mechanism allows activities to be notified of item * selections. @@ -94,91 +102,99 @@ public void onAddConnectionParams() {} public TestListFragment() { } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Resources res = getResources(); - - //Load XML TESTS - TestContent.LoadTests(res.openRawResource(R.raw.tests)); - // TODO: replace with a real list adapter. - - setListAdapter(new ArrayAdapter( - getActivity(), - android.R.layout.simple_list_item_activated_1, - android.R.id.text1, - TestContent.ITEMS)); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - // Restore the previously serialized activated item position. - if (savedInstanceState != null - && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { - setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION)); - } - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - // Activities containing this fragment must implement its callbacks. - if (!(activity instanceof Callbacks)) { - throw new IllegalStateException("Activity must implement fragment's callbacks."); - } - - mCallbacks = (Callbacks) activity; - } - - @Override - public void onDetach() { - super.onDetach(); - - // Reset the active callbacks interface to the dummy implementation. - mCallbacks = sDummyCallbacks; - } - - @Override - public void onListItemClick(ListView listView, View view, int position, long id) { - super.onListItemClick(listView, view, position, id); - - // Notify the active callbacks interface (the activity, if the - // fragment is attached to one) that an item has been selected. - mCallbacks.onItemSelected(TestContent.ITEMS.get(position).id); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (mActivatedPosition != ListView.INVALID_POSITION) { - // Serialize and persist the activated item position. - outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition); - } - } - - /** - * Turns on activate-on-click mode. When this mode is on, list items will be - * given the 'activated' state when touched. - */ - public void setActivateOnItemClick(boolean activateOnItemClick) { - // When setting CHOICE_MODE_SINGLE, ListView will automatically - // give items the 'activated' state when touched. - getListView().setChoiceMode(activateOnItemClick - ? ListView.CHOICE_MODE_SINGLE - : ListView.CHOICE_MODE_NONE); - } - - private void setActivatedPosition(int position) { - if (position == ListView.INVALID_POSITION) { - getListView().setItemChecked(mActivatedPosition, false); - } else { - getListView().setItemChecked(position, true); - } - - mActivatedPosition = position; - } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Resources res = getResources(); + TestContent.LoadTests(res.openRawResource(R.raw.tests)); + + // Initialize the adapter here, but set it to the ListView in onViewCreated + mAdapter = new ArrayAdapter<>( + requireActivity(), // Use requireActivity() for non-null Context + android.R.layout.simple_list_item_activated_1, + android.R.id.text1, + TestContent.ITEMS + ); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragement_test_list, container, false); + return view; + } + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mListView = view.findViewById(R.id.test_list_view); // Get reference to ListView + mListView.setAdapter(mAdapter); // Set the adapter + + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + // Notify the active callbacks interface (the activity, if the + // fragment is attached to one) that an item has been selected. + if (TestContent.ITEMS.size() > position) { // Ensure position is valid + mCallbacks.onItemSelected(TestContent.ITEMS.get(position).id); + // Update activated position for two-pane UIs + if (mListView.getChoiceMode() == ListView.CHOICE_MODE_SINGLE) { + mActivatedPosition = position; + } + } + } + }); + + // Restore the previously serialized activated item position. + if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { + setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION)); + } + } + + @Override + public void onAttach(@NonNull Context context) { // Changed from Activity, added @NonNull + super.onAttach(context); + if (context instanceof Callbacks) { + mCallbacks = (Callbacks) context; + } else { + throw new IllegalStateException(context.toString() + " must implement fragment's callbacks."); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mCallbacks = sDummyCallbacks; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { // Added @NonNull + super.onSaveInstanceState(outState); + if (mActivatedPosition != ListView.INVALID_POSITION) { + outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition); + } + } + + public void setActivateOnItemClick(boolean activateOnItemClick) { + if (mListView != null) { // Ensure ListView is initialized + mListView.setChoiceMode(activateOnItemClick + ? ListView.CHOICE_MODE_SINGLE + : ListView.CHOICE_MODE_NONE); + } + } + + private void setActivatedPosition(int position) { + if (mListView == null) return; // Guard against null ListView + + if (position == ListView.INVALID_POSITION) { + mListView.setItemChecked(mActivatedPosition, false); + } else { + mListView.setItemChecked(position, true); + } + mActivatedPosition = position; + } } diff --git a/app/src/main/java/red5pro/org/testandroidproject/tests/ParamTable/ParamTable.java b/app/src/main/java/red5pro/org/testandroidproject/tests/ParamTable/ParamTable.java index 3a0cafb..30a35dd 100644 --- a/app/src/main/java/red5pro/org/testandroidproject/tests/ParamTable/ParamTable.java +++ b/app/src/main/java/red5pro/org/testandroidproject/tests/ParamTable/ParamTable.java @@ -1,6 +1,6 @@ package red5pro.org.testandroidproject.tests.ParamTable; -import android.app.Fragment; +import androidx.fragment.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.MotionEvent; diff --git a/app/src/main/res/layout/fragement_test_list.xml b/app/src/main/res/layout/fragement_test_list.xml new file mode 100644 index 0000000..5a76ceb --- /dev/null +++ b/app/src/main/res/layout/fragement_test_list.xml @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ff6c9d2..766ab99 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - diff --git a/build.gradle b/build.gradle index aa9b0a0..c6021e2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '2.2.0' repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:8.13.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -17,7 +18,6 @@ buildscript { allprojects { repositories { jcenter() - google() } } diff --git a/gradle.properties b/gradle.properties index 643cb25..150ce6f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,7 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -android.useAndroidX = true \ No newline at end of file +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false +android.nonTransitiveRClass=false +android.useAndroidX = true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f48f5a9..36509fd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip diff --git a/streaming-android.iml b/streaming-android.iml deleted file mode 100644 index 67c38b3..0000000 --- a/streaming-android.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file