Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ android {

buildFeatures {
viewBinding true
dataBinding true
buildConfig true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public NativeAdBannerView(@NonNull Context context, @Nullable AttributeSet attrs

private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NativeAdBannerView, defStyleAttr, 0);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NativeAdBannerView, defStyleAttr, 0); // FIXME: 'TypedArray' used without 'try'-with-resources statement
layoutRes = a.getResourceId(R.styleable.NativeAdBannerView_nativeAdLayout, R.layout.ad_home_banner_large);
a.recycle();
}
Expand All @@ -49,7 +49,7 @@ public void loadAd(AdRequest adRequest) {
loadAd(adRequest, null);
}

public void loadAd(AdRequest adRequest, @Nullable AdListener listener) {
public void loadAd(AdRequest adRequest, @Nullable AdListener listener) { // FIXME: Parameter 'adRequest' is never used
NativeAdLoader.load(getContext(), this, layoutRes, listener);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public String getAppPlayStoreUrl(String packageName) {
}

@Override
public String getDailyTip() {
public String dailyTip() {
return localDataSource.getDailyTip();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface HomeRepository {

String getAppPlayStoreUrl(String packageName);

String getDailyTip();
String dailyTip();

void fetchPromotedApps(PromotedAppsCallback callback);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public GetDailyTipUseCase(HomeRepository repository) {
* Returns today's tip string.
*/
public String invoke() {
return repository.getDailyTip();
return repository.dailyTip();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public android.view.View onCreateView(@NonNull android.view.LayoutInflater infla
});

binding.imageViewAppIcon.setOnClickListener(
v -> openUrl("https://d4rk7355608.github.io/home/"));
v -> openUrl("https://mihaicristiancondrea.github.io/profile"));
binding.chipGoogleDev.setOnClickListener(
v -> openUrl("https://g.dev/D4rK7355608"));
binding.chipYoutube.setOnClickListener(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ protected void onDestroy() {

private static class NotesAdapter extends ListAdapter<Note, NotesAdapter.NoteViewHolder> {
private static final DiffUtil.ItemCallback<Note> DIFF_CALLBACK =
new DiffUtil.ItemCallback<Note>() {
new DiffUtil.ItemCallback<>() {
@Override
public boolean areItemsTheSame(@NonNull Note oldItem, @NonNull Note newItem) {
return oldItem.id == newItem.id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

binding.buttonFetch.setOnClickListener(v -> {
binding.buttonFetch.setEnabled(false);
api.getTodo().enqueue(new Callback<Todo>() {
api.getTodo().enqueue(new Callback<>() {
@Override
public void onResponse(Call<Todo> call, Response<Todo> response) {
public void onResponse(Call<Todo> call, Response<Todo> response) { // FIXME: Not annotated parameter overrides @EverythingIsNonNull parameter
if (response.isSuccessful() && response.body() != null) {
binding.textViewResult.setText(response.body().title);
} else {
Expand All @@ -56,7 +56,7 @@ public void onResponse(Call<Todo> call, Response<Todo> response) {
}

@Override
public void onFailure(Call<Todo> call, Throwable t) {
public void onFailure(Call<Todo> call, Throwable t) { // FIXME: Not annotated parameter overrides @EverythingIsNonNull parameter
binding.textViewResult.setText(R.string.snack_general_error);
binding.buttonFetch.setEnabled(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected void onCreate(Bundle savedInstanceState) {
edgeToEdgeDelegate.applyEdgeToEdge(binding.constraintLayout);

setSupportActionBar(binding.topAppBar);
binding.topAppBar.setNavigationOnClickListener(v -> onBackPressed());
binding.topAppBar.setNavigationOnClickListener(v -> onBackPressed()); // FIXME: 'onBackPressed()' is deprecated
binding.topAppBar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.action_share) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void hidePassword() {

private void addKeyListener() {
binding.buttonShowPassword.setOnClickListener(v ->
Snackbar.make(binding.getRoot(), binding.editText.getText(), Snackbar.LENGTH_LONG).show());
Snackbar.make(binding.getRoot(), binding.editText.getText(), Snackbar.LENGTH_LONG).show()); // FIXME: Argument 'binding.editText.getText()' might be null
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected void onCreate(Bundle savedInstanceState) {
@SuppressLint("SetJavaScriptEnabled")
private void setupWebView() {
WebView webView = binding.webView;
webView.loadUrl("https://d4rk7355608.github.io/profile/#home");
webView.loadUrl("https://mihaicristiancondrea.github.io/profile/");
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
openLink("https://play.google.com/apps/testing/" + getPackageName());
return true;
} else if (itemId == R.id.terms_of_service) {
openLink("https://d4rk7355608.github.io/profile/#terms-of-service-apps");
openLink("https://mihaicristiancondrea.github.io/profile/#terms-of-service-end-user-software");
return true;
} else if (itemId == R.id.privacy_policy) {
openLink("https://d4rk7355608.github.io/profile/#privacy-policy-apps");
openLink("https://mihaicristiancondrea.github.io/profile/#privacy-policy-end-user-software");
return true;
} else if (itemId == R.id.oss) {
OpenSourceLicensesUtils.loadHtmlData(this, (changelogHtml, eulaHtml) -> openLicensesScreen(this, eulaHtml, changelogHtml));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private void shareTip(String tip) {
private void shareApp(com.d4rk.androidtutorials.java.data.model.PromotedApp app) {
android.content.Intent sharingIntent = new android.content.Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String shareLink = homeViewModel.getPromotedAppIntent(app.packageName()).getData().toString();
String shareLink = homeViewModel.getPromotedAppIntent(app.packageName()).getData().toString(); // FIXME: Method invocation 'toString' may produce 'NullPointerException'
String shareMessage = getString(com.d4rk.androidtutorials.java.R.string.share_message, shareLink);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareMessage);
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(com.d4rk.androidtutorials.java.R.string.share_subject));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,21 @@ public void onResume(@NonNull LifecycleOwner owner) {
if (ConsentUtils.canShowAds(MainActivity.this)) {
if (mBinding.adView.getVisibility() != View.VISIBLE) {
MobileAds.initialize(MainActivity.this);
mBinding.adPlaceholder.setVisibility(View.GONE);
mBinding.adPlaceholder.setVisibility(View.GONE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
mBinding.adView.setVisibility(View.VISIBLE);
mBinding.adView.loadAd(new AdRequest.Builder().build());
}
} else {
mBinding.adView.setVisibility(View.GONE);
mBinding.adPlaceholder.setVisibility(View.VISIBLE);
mBinding.adPlaceholder.setVisibility(View.VISIBLE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
}
}
}
};
private MainViewModel mainViewModel;
private NavController navController;
private int currentNavIndex;
private AppUpdateNotificationsManager appUpdateNotificationsManager;
private AppUpdateNotificationsManager appUpdateNotificationsManager; // FIXME: Private field 'appUpdateNotificationsManager' is assigned but never accessed
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;
private long backPressedTime;
Expand Down Expand Up @@ -173,24 +173,24 @@ private void observeViewModel() {
EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
NavigationBarView navBarView = (NavigationBarView) mBinding.navView;
if (useRail) {
mBinding.navRail.setVisibility(View.VISIBLE);
mBinding.navRail.setVisibility(View.VISIBLE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
navBarView.setVisibility(View.GONE);
edgeToEdgeDelegate.applyEdgeToEdge(mBinding.container);
} else {
mBinding.navRail.setVisibility(View.GONE);
mBinding.navRail.setVisibility(View.GONE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
navBarView.setVisibility(View.VISIBLE);
edgeToEdgeDelegate.applyEdgeToEdgeBottomBar(mBinding.container, navBarView);

navBarView.setLabelVisibilityMode(uiState.getBottomNavVisibility());
navBarView.setLabelVisibilityMode(uiState.bottomNavVisibility());
if (mBinding.adView != null) {
if (ConsentUtils.canShowAds(this)) {
MobileAds.initialize(this);
mBinding.adPlaceholder.setVisibility(View.GONE);
mBinding.adPlaceholder.setVisibility(View.GONE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
mBinding.adView.setVisibility(View.VISIBLE);
mBinding.adView.loadAd(new AdRequest.Builder().build());
} else {
mBinding.adView.setVisibility(View.GONE);
mBinding.adPlaceholder.setVisibility(View.VISIBLE);
mBinding.adPlaceholder.setVisibility(View.VISIBLE); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
}
}
}
Expand All @@ -200,13 +200,13 @@ private void observeViewModel() {
if (navHostFragment != null) {
navController = navHostFragment.getNavController();
NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.mobile_navigation);
navGraph.setStartDestination(uiState.getDefaultNavDestination());
navGraph.setStartDestination(uiState.defaultNavDestination());
navController.setGraph(navGraph);

navOrder.put(R.id.navigation_home, 0);
navOrder.put(R.id.navigation_android_studio, 1);
navOrder.put(R.id.navigation_about, 2);
currentNavIndex = navOrder.get(navController.getCurrentDestination().getId());
currentNavIndex = navOrder.get(navController.getCurrentDestination().getId()); // FIXME: Method invocation 'getId' may produce 'NullPointerException'

NavOptions forwardOptions = new NavOptions.Builder()
.setEnterAnim(R.anim.fragment_spring_enter)
Expand Down Expand Up @@ -256,13 +256,13 @@ private void observeViewModel() {
});
}

if (uiState.isThemeChanged()) {
if (uiState.themeChanged()) {
recreate();
}
});

mainViewModel.getLoadingState().observe(this, isLoading ->
mBinding.progressBar.setVisibility(Boolean.TRUE.equals(isLoading) ? View.VISIBLE : View.GONE));
mBinding.progressBar.setVisibility(Boolean.TRUE.equals(isLoading) ? View.VISIBLE : View.GONE)); // FIXME: Method invocation 'setVisibility' may produce 'NullPointerException'
}

private void setupUpdateNotifications() {
Expand All @@ -285,7 +285,8 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) {
return super.onOptionsItemSelected(item);
}

private void checkForImmediateUpdate() {
// TODO: Call on onResume
private void checkForImmediateUpdate() { // FIXME: Private method 'checkForImmediateUpdate()' is never used
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@
* bottom navigation visibility, the default navigation destination, and whether the theme
* has changed requiring a recreation of the activity.
*/
public class MainUiState {
@NavigationBarView.LabelVisibility
private final int bottomNavVisibility;
private final int defaultNavDestination;
private final boolean themeChanged;

public MainUiState(@NavigationBarView.LabelVisibility int bottomNavVisibility, int defaultNavDestination, boolean themeChanged) {
this.bottomNavVisibility = bottomNavVisibility;
this.defaultNavDestination = defaultNavDestination;
this.themeChanged = themeChanged;
}

@NavigationBarView.LabelVisibility
public int getBottomNavVisibility() {
return bottomNavVisibility;
}

public int getDefaultNavDestination() {
return defaultNavDestination;
}

public boolean isThemeChanged() {
return themeChanged;
}
public record MainUiState(@NavigationBarView.LabelVisibility int bottomNavVisibility,
int defaultNavDestination, boolean themeChanged) {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.d4rk.androidtutorials.java.ui.screens.onboarding;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -11,6 +13,10 @@
import androidx.lifecycle.ViewModelProvider;

import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingDataBinding;
import com.d4rk.androidtutorials.java.utils.ConsentUtils;
import androidx.preference.PreferenceManager;
import android.content.SharedPreferences;
import com.d4rk.androidtutorials.java.R;

public class DataFragment extends Fragment {

Expand All @@ -28,6 +34,44 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(requireActivity()).get(OnboardingViewModel.class);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
String keyAnalytics = getString(R.string.key_consent_analytics);
String keyAdPersonalization = getString(R.string.key_consent_ad_personalization);

boolean analytics = prefs.getBoolean(keyAnalytics, true);
boolean ads = prefs.getBoolean(keyAdPersonalization, true);
binding.switchCrashlytics.setChecked(analytics);
binding.switchAds.setChecked(ads);

binding.switchCrashlytics.setOnCheckedChangeListener((buttonView, isChecked) -> {
viewModel.setCrashlyticsEnabled(isChecked);
viewModel.setConsentAnalytics(isChecked);
ConsentUtils.updateFirebaseConsent(requireContext(), isChecked, binding.switchAds.isChecked(), binding.switchAds.isChecked(), binding.switchAds.isChecked());
});

binding.switchAds.setOnCheckedChangeListener((buttonView, isChecked) -> {
viewModel.setConsentAdStorage(isChecked);
viewModel.setConsentAdUserData(isChecked);
viewModel.setConsentAdPersonalization(isChecked);
ConsentUtils.updateFirebaseConsent(requireContext(), binding.switchCrashlytics.isChecked(), isChecked, isChecked, isChecked);
});

binding.linkPrivacy.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://mihaicristiancondrea.github.io/profile/#privacy-policy-end-user-software"));
startActivity(intent);
});
}

public void saveSelection() {
boolean analytics = binding.switchCrashlytics.isChecked();
boolean ads = binding.switchAds.isChecked();
viewModel.setCrashlyticsEnabled(analytics);
viewModel.setConsentAnalytics(analytics);
viewModel.setConsentAdStorage(ads);
viewModel.setConsentAdUserData(ads);
viewModel.setConsentAdPersonalization(ads);
ConsentUtils.updateFirebaseConsent(requireContext(), analytics, ads, ads, ads);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.d4rk.androidtutorials.java.ui.screens.onboarding;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.d4rk.androidtutorials.java.databinding.FragmentOnboardingDoneBinding;

public class DoneFragment extends Fragment {

private FragmentOnboardingDoneBinding binding;
private OnboardingViewModel viewModel;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentOnboardingDoneBinding.inflate(inflater, container, false);
return binding.getRoot();
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(requireActivity()).get(OnboardingViewModel.class);
binding.buttonGetStarted.setOnClickListener(v -> {
viewModel.markOnboardingComplete();
if (getActivity() instanceof OnboardingActivity) {
((OnboardingActivity) getActivity()).finishOnboarding();
}
});
}

@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
Loading
Loading