Skip to content

Commit e64d5cc

Browse files
NmurtasDevclaude
andcommitted
Add Android SDK license agreement dialog before download
- Show official Android SDK License Agreement before SDK download - Include key sections: Introduction, Accepting License, SDK License terms - Display scrollable text area with full license text - Add clickable link to view full license at developer.android.com/studio/terms - Link opens in system default browser - Two buttons: "I Accept" (allows download) and "I Decline" (cancels) - Default selection is "I Decline" for safety - Log user's acceptance/decline decision - Prevent SDK download if license is not accepted - Comply with Google's licensing requirements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f0c0099 commit e64d5cc

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

src/main/java/net/nicolamurtas/android/emulator/AndroidEmulatorManager.java

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import javax.swing.*;
1111
import java.awt.*;
12+
import java.awt.Desktop;
1213
import java.nio.file.Files;
1314
import java.nio.file.Path;
1415
import java.util.*;
@@ -595,6 +596,12 @@ private void downloadSdk() {
595596

596597
Path sdkPath = Path.of(pathText);
597598

599+
// Show license agreement first
600+
if (!showLicenseAgreementDialog()) {
601+
log("SDK download cancelled: License not accepted");
602+
return;
603+
}
604+
598605
// Show component selection dialog
599606
List<String> selectedComponents = showSdkComponentSelectionDialog();
600607
if (selectedComponents == null || selectedComponents.isEmpty()) {
@@ -632,6 +639,144 @@ private void downloadSdk() {
632639
}).start();
633640
}
634641

642+
/**
643+
* Shows the Android SDK License Agreement dialog.
644+
* User must accept to proceed with SDK download.
645+
*
646+
* @return true if user accepted, false otherwise
647+
*/
648+
private boolean showLicenseAgreementDialog() {
649+
String licenseText = """
650+
ANDROID SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT
651+
652+
1. Introduction
653+
654+
1.1 The Android Software Development Kit (referred to in the License Agreement as the "SDK"
655+
and specifically including the Android system files, packaged APIs, and Google APIs add-ons)
656+
is licensed to you subject to the terms of the License Agreement. The License Agreement forms
657+
a legally binding contract between you and Google in relation to your use of the SDK.
658+
659+
1.2 "Android" means the Android software stack for devices, as made available under the
660+
Android Open Source Project, which is located at the following URL:
661+
https://source.android.com/, as updated from time to time.
662+
663+
1.3 A "compatible implementation" means any Android device that (i) complies with the Android
664+
Compatibility Definition document, which can be found at the Android compatibility website
665+
(https://source.android.com/compatibility) and which may be updated from time to time; and
666+
(ii) successfully passes the Android Compatibility Test Suite (CTS).
667+
668+
1.4 "Google" means Google LLC, a Delaware corporation with principal place of business at
669+
1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
670+
671+
672+
2. Accepting this License Agreement
673+
674+
2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use
675+
the SDK if you do not accept the License Agreement.
676+
677+
2.2 By clicking to accept, you hereby agree to the terms of the License Agreement.
678+
679+
2.3 You may not use the SDK and may not accept the License Agreement if you are a person
680+
barred from receiving the SDK under the laws of the United States or other countries,
681+
including the country in which you are resident or from which you use the SDK.
682+
683+
2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or
684+
other entity, you represent and warrant that you have full legal authority to bind your
685+
employer or such entity to the License Agreement. If you do not have the requisite authority,
686+
you may not accept the License Agreement or use the SDK on behalf of your employer or other
687+
entity.
688+
689+
690+
3. SDK License from Google
691+
692+
3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide,
693+
royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK
694+
solely to develop applications for compatible implementations of Android.
695+
696+
3.2 You may not use this SDK to develop applications for other platforms (including
697+
non-compatible implementations of Android) or to develop another SDK. You are of course free
698+
to develop applications for other platforms, including non-compatible implementations of
699+
Android, provided that this SDK is not used for that purpose.
700+
701+
3.3 You agree that Google or third parties own all legal right, title and interest in and to
702+
the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual
703+
Property Rights" means any and all rights under patent law, copyright law, trade secret law,
704+
trademark law, and any and all other proprietary rights. Google reserves all rights not
705+
expressly granted to you.
706+
707+
708+
For the complete license agreement, please visit:
709+
https://developer.android.com/studio/terms
710+
711+
712+
BY CLICKING "I ACCEPT" BELOW, YOU ACKNOWLEDGE THAT YOU HAVE READ AND UNDERSTOOD THE ABOVE
713+
TERMS AND CONDITIONS AND AGREE TO BE BOUND BY THEM.
714+
""";
715+
716+
JTextArea textArea = new JTextArea(licenseText);
717+
textArea.setEditable(false);
718+
textArea.setLineWrap(true);
719+
textArea.setWrapStyleWord(true);
720+
textArea.setCaretPosition(0);
721+
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 11));
722+
723+
JScrollPane scrollPane = new JScrollPane(textArea);
724+
scrollPane.setPreferredSize(new Dimension(700, 500));
725+
726+
JPanel panel = new JPanel(new BorderLayout(10, 10));
727+
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
728+
729+
JLabel titleLabel = new JLabel("Android SDK License Agreement");
730+
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 16f));
731+
panel.add(titleLabel, BorderLayout.NORTH);
732+
733+
panel.add(scrollPane, BorderLayout.CENTER);
734+
735+
JPanel bottomPanel = new JPanel(new BorderLayout());
736+
JLabel noteLabel = new JLabel("<html><b>Note:</b> You must accept this license to download and use the Android SDK.</html>");
737+
noteLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
738+
bottomPanel.add(noteLabel, BorderLayout.NORTH);
739+
740+
JPanel linkPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
741+
JButton linkButton = new JButton("View Full License at developer.android.com");
742+
linkButton.setBorderPainted(false);
743+
linkButton.setContentAreaFilled(false);
744+
linkButton.setForeground(new Color(33, 150, 243));
745+
linkButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
746+
linkButton.addActionListener(e -> {
747+
try {
748+
Desktop.getDesktop().browse(new java.net.URI("https://developer.android.com/studio/terms"));
749+
} catch (Exception ex) {
750+
logger.warn("Could not open browser", ex);
751+
}
752+
});
753+
linkPanel.add(linkButton);
754+
bottomPanel.add(linkPanel, BorderLayout.SOUTH);
755+
756+
panel.add(bottomPanel, BorderLayout.SOUTH);
757+
758+
Object[] options = {"I Accept", "I Decline"};
759+
int result = JOptionPane.showOptionDialog(
760+
this,
761+
panel,
762+
"Android SDK License Agreement",
763+
JOptionPane.YES_NO_OPTION,
764+
JOptionPane.PLAIN_MESSAGE,
765+
null,
766+
options,
767+
options[1] // Default to "I Decline"
768+
);
769+
770+
boolean accepted = (result == JOptionPane.YES_OPTION);
771+
if (accepted) {
772+
log("Android SDK License Agreement accepted by user");
773+
} else {
774+
log("Android SDK License Agreement declined by user");
775+
}
776+
777+
return accepted;
778+
}
779+
635780
private List<String> showSdkComponentSelectionDialog() {
636781
JPanel panel = new JPanel(new GridBagLayout());
637782
GridBagConstraints gbc = new GridBagConstraints();

0 commit comments

Comments
 (0)