Does anyone know how to hack this game like to get more money and stuff?
Also looking for an answer.
i have found this file
/data/data/com.droidhen.defender/shared_prefs
save0.xml
tried to edit the values with root unsuccessful its back to original values or a blank file
for gold and magic stone have this checkValue hash
Code:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<int name="fireLevel2" value="1" />
<int name="singleRetry" value="1" />
<int name="magicStone" value="3" />
<int name="equipMagic3" value="0" />
<int name="equipMagic2" value="0" />
<int name="fireLevel1" value="3" />
<int name="equipMagic1" value="1" />
<int name="agilityLevel" value="10" />
<int name="equipBow" value="2" />
<string name="magicStonecheckValue">575766027f156ec80b56c2b4aff29fa1</string>
<int name="bowLock4" value="1" />
<int name="stage" value="50" />
<int name="bowLock2" value="1" />
<int name="powerShotLevel" value="3" />
<int name="bowLock1" value="1" />
<int name="multiArrowLevel" value="1" />
<int name="iceLevel1" value="1" />
<int name="strengthLevel" value="5" />
<string name="goldcheckValue">989805d0d941ac7e095829e801e0eb2a</string>
<int name="guardLevel" value="4" />
<int name="lightLevel1" value="1" />
<int name="fatalBlowLevel" value="3" />
<int name="totalRetry" value="24" />
<int name="gold" value="745" />
<int name="hardMode" value="0" />
</map>
goruks said:
i have found this file
/data/data/com.droidhen.defender/shared_prefs
save0.xml
tried to edit the values with root unsuccessful its back to original values or a blank file
for gold and magic stone have this checkValue hash
Click to expand...
Click to collapse
for me on galaxy s is under
/dbdata/databases/com.droidhen.defender/shared_prefs
i've tried to modify but when i start the game i've all save reset
we need to calculate the check value
i've dot it
if u want help write send private message
actually you can try this app gamecih2
it acts like the cheat engine, if you know how to use cheat engine in pc then you surely can use this
Figured anything out yet? Would love to know
Gamecih2 works
Sent from my Incredible using xda premium
It simple
Edit: Kill the game in task manager before edit the file.
the checkvalue is very simple, it's only the md5 hash of the value + the string "checkChar", look:
If you want 100000 magicStone, you do:
magicStone = 100000
magicStonecheckValue = md5(100000+"checkChar") = 758ea9ef9ae80ea41e11083fedf29205
the same for gold.
Enjoy
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
here the piece of game code:
Code:
public static int loadData(String paramString, int paramInt)
{
int i = GameProfile.getDefaultValue(paramString);
int j = _saves[paramInt].getInt(paramString, i);
String str;
if ((paramString == "gold") || (paramString == "magicStone"))
{
str = _saves[paramInt].getString(paramString + "checkValue", "");
if (str.equals(""))
{
if (paramString == "magicStone")
str = "4e29b81cc5d7d3b5396952312579e241";
}
else
{
if (checkSum(j, str))
break label119;
clearData(paramInt);
}
}
label119: for (int k = 0; ; k = j)
{
return k;
if (paramString != "gold")
break;
str = "76de858b1664d23221ab412ed4abbb51";
break;
}
}
Masterfish said:
the checkvalue is very simple, it's only the md5 hash of the value + the string "checkChar", look:
If you want 100000 magicStone, you do:
magicStone = 100000
magicStonecheckValue = md5(100000+"checkChar") = 758ea9ef9ae80ea41e11083fedf29205
the same for gold.
Enjoy
here the piece of game code:
Code:
public static int loadData(String paramString, int paramInt)
{
int i = GameProfile.getDefaultValue(paramString);
int j = _saves[paramInt].getInt(paramString, i);
String str;
if ((paramString == "gold") || (paramString == "magicStone"))
{
str = _saves[paramInt].getString(paramString + "checkValue", "");
if (str.equals(""))
{
if (paramString == "magicStone")
str = "4e29b81cc5d7d3b5396952312579e241";
}
else
{
if (checkSum(j, str))
break label119;
clearData(paramInt);
}
}
label119: for (int k = 0; ; k = j)
{
return k;
if (paramString != "gold")
break;
str = "76de858b1664d23221ab412ed4abbb51";
break;
}
}
Click to expand...
Click to collapse
That was a real help, but it seems the changes I make on it gets washed away when I start the game. Do you know what is going on?
I used root explorer to locate the save file and using text editor changed gold value and goldcheckvalue with the md5 hash I got using "100000checkChar" then save/exit to start the game again. What am I doing wrong?
the root explorer creates a backup file, make sure you delete it
I muddle " md5(100000+"checkChar") "
I want 1000000 what the code for this number ???
hakee100 said:
I muddle " md5(100000+"checkChar") "
I want 1000000 what the code for this number ???
Click to expand...
Click to collapse
magicStone = 1000000
magicStonecheckValue = dcfe797e9af072535072c8f3a3595675
edit all leves at xml, save and delete the .bak before run game
Can't find the file
I looked in both path written earlier but i can't find the save file to modify...
I have a SGS with 2.3.3
Thank you
Can't edit the file
Hi,
Sorry for my bad English but i'm French.
I have a problem : I can't edit the xml file with root explorer.
How can I change the values ? Do I need a xml editor ? Wich one ?
I hope you will be able to help me ^^
Thanks
I'm completely confused. I've never done this sort of editing. I tried using Gamecih2 but that didn't get me anywhere. Now I'm trying to follow everything you guys are saying, however, I can't even locate the damn file. I check droidhen and all I see is a file called pmdatas. When I open it with XML editor or even Notepad, all it says is "1. Defender"
Any help? Anyone wanna make a video guide?
Fine. now i got enough magic stone, but i wonder whats the code for 1000000 gold? :/
Masterfish said:
post
Click to expand...
Click to collapse
need help.. i dont know where to find the file to edit.. i am using a galaxy s.. and im using root explorer to find the shared_pref but i cant find it.. please help
can anyone please tell me what file to edit in samsung galaxy S.. cant find save0 or shared_pref just like plangevin i cant find the file to edit
Related
Hello Folks,
some time ago I did some examination on the diagnostics tool included with every firmware. I did not make any siginficant progress because most of the things I tried reqiuired certificates and signed libraries. However I want to share my thoughts so maybe someone else is able to do smoething with this tool..
The main "vulnerability" in the diagnostics tool is that it tries to load every DLL that is defined as AssemblyPart. Here is the MainPage Constructor
Code:
public MainPage()
{
base.\u002Ector();
this.InitializeComponent();
this.oddtMenuItems = new List<OddtMenuItem>();
AssemblyPartCollection parts = Deployment.Current.Parts;
RadioTechnology radio = this.GetRadio();
bool flag = this.isLTEnabled();
foreach (AssemblyPart assemblyPart in (PresentationFrameworkCollection<AssemblyPart>) parts)
{
try
{
Assembly assembly = Assembly.Load(assemblyPart.Source.Replace(".dll", string.Empty));
OddtMenuItem oddtMenuItem = (OddtMenuItem) Enumerable.FirstOrDefault<object>((IEnumerable<object>) assembly.GetCustomAttributes(typeof (OddtMenuItem), true));
if (oddtMenuItem != null)
{
if (!assembly.Equals((object) Assembly.GetExecutingAssembly()))
{
if (oddtMenuItem.RadioType != RadioTechnology.NA && (oddtMenuItem.RadioType & radio) == RadioTechnology.NA)
oddtMenuItem.setEnabled(false);
if (oddtMenuItem.Title == "Wireless LAN" || oddtMenuItem.Title == "APN Settings")
{
oddtMenuItem.setEnabled(false);
this.oddtMenuItems.Remove(oddtMenuItem);
}
if (oddtMenuItem.Title == "Life Timer" && !flag)
{
oddtMenuItem.setEnabled(false);
this.oddtMenuItems.Remove(oddtMenuItem);
}
this.oddtMenuItems.Add(oddtMenuItem);
}
}
}
catch (Exception ex)
{
}
}
this.PrioritizeMenuItems();
this.MainListBox.DataContext = (object) this.oddtMenuItems;
if ((bool) Application.Current.Resources[(object) "OddtDisclaimerAccepted"])
{
this.ContentGrid.Visibility = Visibility.Visible;
this.DisclaimerGrid.Visibility = Visibility.Collapsed;
this.get_ApplicationBar().set_IsVisible(true);
}
else
{
this.ContentGrid.Visibility = Visibility.Collapsed;
this.DisclaimerGrid.Visibility = Visibility.Visible;
this.get_ApplicationBar().set_IsVisible(false);
}
}
The AssemblyParts are defined in the WMAppManifest.xaml:
Code:
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="OddtApplication" EntryPointType="OddtApplication.App" RuntimeVersion="4.7.50308.0">
<Deployment.Parts>
<AssemblyPart x:Name="OddtApplication" Source="OddtApplication.dll" />
<AssemblyPart x:Name="About" Source="About.dll" />
<AssemblyPart x:Name="Accelerometer" Source="Accelerometer.dll" />
<AssemblyPart x:Name="Als" Source="Als.dll" />
<AssemblyPart x:Name="APN" Source="APN.dll" />
<AssemblyPart x:Name="AudioLoopback" Source="AudioLoopback.dll" />
<AssemblyPart x:Name="Battery" Source="Battery.dll" />
<AssemblyPart x:Name="Bluetooth" Source="Bluetooth.dll" />
<AssemblyPart x:Name="Camera" Source="Camera.dll" />
<AssemblyPart x:Name="CareBattery" Source="CareBattery.dll" />
<AssemblyPart x:Name="CareTestSequence" Source="CareTestSequence.dll" />
<AssemblyPart x:Name="Dtmf" Source="Dtmf.dll" />
<AssemblyPart x:Name="ExampleLibrary" Source="ExampleLibrary.dll" />
<AssemblyPart x:Name="Gyroscope" Source="Gyroscope.dll" />
<AssemblyPart x:Name="HardwareButtons" Source="HardwareButtons.dll" />
<AssemblyPart x:Name="Headset" Source="Headset.dll" />
<AssemblyPart x:Name="LcdWhite" Source="LcdWhite.dll" />
<AssemblyPart x:Name="LedKeypad" Source="LedKeypad.dll" />
<AssemblyPart x:Name="LifeTimer" Source="LifeTimer.dll" />
<AssemblyPart x:Name="LTEBandLock" Source="LTEBandLock.dll" />
<AssemblyPart x:Name="LTETx" Source="LTETx.dll" />
<AssemblyPart x:Name="Magnetometer" Source="Magnetometer.dll" />
<AssemblyPart x:Name="Memory" Source="Memory.dll" />
<AssemblyPart x:Name="Microsoft.Phone.Controls" Source="Microsoft.Phone.Controls.dll" />
<AssemblyPart x:Name="Microsoft.Phone.Controls.Toolkit" Source="Microsoft.Phone.Controls.Toolkit.dll" />
<AssemblyPart x:Name="MMS" Source="MMS.dll" />
<AssemblyPart x:Name="NonLinearNavigationService" Source="NonLinearNavigationService.dll" />
<AssemblyPart x:Name="OddtAttributes" Source="OddtAttributes.dll" />
<AssemblyPart x:Name="PowerSource" Source="PowerSource.dll" />
<AssemblyPart x:Name="Proximity" Source="Proximity.dll" />
<AssemblyPart x:Name="RadioAccess" Source="RadioAccess.dll" />
<AssemblyPart x:Name="Settings" Source="Settings.dll" />
<AssemblyPart x:Name="Speaker" Source="Speaker.dll" />
<AssemblyPart x:Name="Touch" Source="Touch.dll" />
<AssemblyPart x:Name="Vibra" Source="Vibra.dll" />
<AssemblyPart x:Name="WirelessLAN" Source="WirelessLAN.dll" />
<AssemblyPart x:Name="Microsoft.Phone.Media.Extended" Source="Microsoft.Phone.Media.Extended.dll" />
</Deployment.Parts>
</Deployment>
For an MenuItem to appear in the diagnostics app it has to be flagged with the OddtMenuItem-Attribute (or however you call this).
Code:
[AttributeUsage(AttributeTargets.Assembly)]
public class OddtMenuItem : Attribute
{
private OddtMenuItemStatus status;
private string title;
private string description;
private Uri entryPage;
private int priority;
private RadioTechnology radiotype;
public Brush ForegroundColor
{
get
{
if (this.status == OddtMenuItemStatus.Alpha)
return (Brush) new SolidColorBrush(Colors.Gray);
if ((Color) ((FrameworkElement) new PhoneApplicationPage()).Resources[(object) "PhoneBackgroundColor"] == Color.FromArgb(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue))
return (Brush) new SolidColorBrush(Colors.Black);
else
return (Brush) new SolidColorBrush(Colors.White);
}
}
public bool IsEnabled
{
get
{
return this.status > OddtMenuItemStatus.Alpha;
}
}
public RadioTechnology RadioType
{
get
{
return this.radiotype;
}
}
public Visibility Visibility
{
get
{
return this.status == (OddtMenuItemStatus.Alpha | OddtMenuItemStatus.Beta) ? Visibility.Visible : Visibility.Collapsed;
}
}
public string Title
{
get
{
return this.title;
}
}
public string Description
{
get
{
return this.description;
}
}
public Uri EntryPage
{
get
{
return this.entryPage;
}
}
public int Priority
{
get
{
return this.priority;
}
set
{
this.priority = value;
}
}
public OddtMenuItem(OddtMenuItemStatus status, string title, string description, string location, RadioTechnology radiotype = RadioTechnology.NA)
{
this.status = status;
this.title = status != OddtMenuItemStatus.Beta ? title : string.Format("{{{0}}}", (object) title);
this.description = description;
this.entryPage = new Uri(location, UriKind.Relative);
this.priority = 99999;
this.radiotype = radiotype;
}
public void setEnabled(bool enable)
{
if (enable)
return;
this.status = OddtMenuItemStatus.Alpha;
}
}
I think that we can execute code with high Level privileges as soon as we are able to manipulate the WMAppManifest.xaml and copy a DLL into the App folder. The main Problem is that every Manipulation of the Folder or one of ist files invalidates the signature.
Regards
Chris
More information like this, you can visit HUAWEI Developer Forum
In a previous post I've written about how to sign in with your Google account in devices without Google Play Services. But, what if a user has a Huawei ID and wants to use it to sign in your app from another device, maybe you can ask the user to install the HMS Core APK, but this can confuse some users. If this is your situation you can use the AppAuth library and the Huawei OAUTH APIs to easily offer the sign in with Huawei for all devices.
Previous requirements
A developer account
An app project on AGC
Adding the required dependencies
For this example we will use the next libraries:
AppAuth: It will allow us to open the sign in page in a web browser and catch the result in our app.
Okio: Required by AppAuth to process data.
Account Kit: Although we won't use the Account Kit capabilities, this dependency allow us to add the Huawei Id Sign In button.
Kotlin Coroutines: Will allow us obtain the user information and download the profile picture without blocking the main thread.
Material Components: Will be used to show a Snackbar telling the user if something went wrong.
Now add the corresponding dependencies in your app leve build.gradle:
Code:
implementation 'net.openid:appauth:0.7.1'
implementation 'com.squareup.okio:okio:1.15.0'
implementation 'com.huawei.agconnect:agconnect-core:1.4.1.300'
implementation 'com.huawei.hms:hwid:5.0.1.301'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
implementation 'com.google.android.material:material:1.2.0'
Configuring AppAuth
Add the next under the "application" node in your AndroidManifest
Code:
<activity android:name="net.openid.appauth.RedirectUriReceiverActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.huawei.apps.APP_ID" />
</intent-filter>
</activity>
Replace APP_ID for your own app Id from the project view on your AGC console
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
App information panel on AGC
Add the next under defaultConfig in your app level build.gradle
Code:
manifestPlaceholders = [
'appAuthRedirectScheme': 'com.huawei.apps.APP_ID'
]
It will look similar to this:
Code:
defaultConfig {
applicationId "com.hms.demo.appauthhuawei"
minSdkVersion 27
targetSdkVersion 29
versionCode 1
versionName "1.0"
manifestPlaceholders = [
'appAuthRedirectScheme': 'com.huawei.apps.102839067'
]
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Code:
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton
android:id="@+id/hwid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="112dp"
app:hwid_button_theme="hwid_button_theme_full_title"
app:hwid_color_policy="hwid_color_policy_black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Login screen
I will use the same activity to show the profile information, but will keep the views hidden until I get the data.
Code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton
android:id="@+id/hwid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="112dp"
app:hwid_button_theme="hwid_button_theme_full_title"
app:hwid_color_policy="hwid_color_policy_black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="216dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars"
android:visibility="gone"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pic"
android:visibility="gone"/>
<TextView
android:id="@+id/mail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/name"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Making the Sign In request
Prepare all the required information to perform the request
Code:
val AUTH_ENDPOINT = "https://oauth-login.cloud.huawei.com/oauth2/v3/authorize"
val TOKEN_ENDPOINT = "https://oauth-login.cloud.huawei.com/oauth2/v3/token"
val APP_ID = "REPLACE WITH YOUR APP ID"
val HW_REDIRECT_URI = "com.huawei.apps.$APP_ID:/oauth2redirect"
val HW_ID_CODE = 100
Note: The endpoints above may change with the time, check this chart to get the current valid endpoints.
Add an OnClickListener to your Sign In button
Code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
hwid.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.hwid -> handleHuaweiId()
}
}
Now is time to perform the request
Code:
private fun handleHuaweiId() {
val serviceConfig = AuthorizationServiceConfiguration(
Uri.parse(AUTH_ENDPOINT), // authorization endpoint
Uri.parse(TOKEN_ENDPOINT)// token endpoint
)
val authRequestBuilder = AuthorizationRequest.Builder(
serviceConfig, // the authorization service configuration
APP_ID, // the client ID, typically pre-registered and static
ResponseTypeValues.CODE, //
Uri.parse(HW_REDIRECT_URI)//The redirect URI
)
authRequestBuilder.setScope("openid email profile")
val authRequest = authRequestBuilder.build()
val authService = AuthorizationService(this)
val authIntent = authService.getAuthorizationRequestIntent(authRequest)
startActivityForResult(authIntent, HW_ID_CODE)
authService.dispose()
}
This will open the Huawei Sign In page on the system default browser.
Huawei Sign In page
Now override the onActivityResult method to get the Sign In result back on your app.
Code:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
HW_ID_CODE -> handleHuaweiSignIn(data)
}
}
You must parse the Auth result to get the Access Token and the ID Token.
Code:
private fun handleHuaweiSignIn(data: Intent?) {
if (data == null) {
return
}
val response = AuthorizationResponse.fromIntent(data)
val ex = AuthorizationException.fromIntent(data)
val authState = AuthState(response, ex)
if (response == null) {
Snackbar.make(hwid, "Response is null, please try again", Snackbar.LENGTH_SHORT).show()
return
}
val service = AuthorizationService(this)
service.performTokenRequest(
response.createTokenExchangeRequest(),
) { tokenResponse, exception ->
service.dispose()
if (tokenResponse == null) {
Snackbar.make(
hwid,
"Token Exchange failed ${exception?.code}",
Snackbar.LENGTH_SHORT
).show()
} else {
authState.update(tokenResponse, exception)
hwid.visibility = View.GONE
obtainUserInfo(tokenResponse.idToken)
}
}
}
The id token contains the user's information encoded in the next format <headers.payload.signature>, so you must decode it to obtain the requested data. Use a coroutine to decode the information and download the user's profile picture.
Note: To get the user's email, you must add "email" to the request scopes and the user must check the email authorization checkbox on the authorization page. If the user doesn't mark the checkbox you won't receive the email.
Code:
private fun obtainUserInfo(idToken: String?) {
CoroutineScope(IO).launch {
if (idToken == null) [email protected]
val json = decoded(idToken)
if (json != null) {
Log.e("JSON", json.toString())
runOnUiThread {
name.text = json.getString("display_name")
name.visibility = View.VISIBLE
if (json.has("email")) {
mail.text = json.getString("email")
mail.visibility = View.VISIBLE
}
}
val bitmap = getBitmap(json.getString("picture"))
if (bitmap != null) {
val resizedBitmap = getResizedBitmap(bitmap, 480, 480)
runOnUiThread {
pic.setImageBitmap(resizedBitmap)
pic.visibility = View.VISIBLE
}
}
}
//val conn=URL("https://oauth-login.cloud.huawei.com/.well-known/openid-configuration").openConnection() as HttpURLConnection
//conn.requestMethod="POST"
}
}
@Throws(Exception::class)
private fun decoded(JWTEncoded: String): JSONObject? {
try {
val split = JWTEncoded.split(".").toTypedArray()
return JSONObject(getJson(split[1]))
} catch (e: UnsupportedEncodingException) {
//Error
return null
}
}
@Throws(UnsupportedEncodingException::class)
private fun getJson(strEncoded: String): String {
val decodedBytes: ByteArray = Base64.decode(strEncoded, Base64.URL_SAFE)
return String(decodedBytes, StandardCharsets.UTF_8)
}
}
Profile Screen
Conclusion
Now all your users can use their Huawei IDs to Sign In your app, even in non-Huawei devices. To keep the user signed I recommend you to use Huawei Auth Service.
Check the full example here: https://github.com/DTSE-HWI-Q-A/AppAuthHuawei
Reference
https://developer.huawei.com/consumer/en/doc/HMSCore-Guides-V5/app-auth-access-huaweiid-0000001050434521-V5
Excellent, thank you
Article Introduction
In this article we will show Huawei Map as popup in three different ways. By using Dialogs, separate Activity and separate Fragment. We can explore some of the restrictions and advantages of show Huawei Map as Popup in different methodologies.
Huawei Map Kit
Personalizing how your map displays and interacts with your users tailors their experience to them, not the other way around. Make location-based services work better for you so your app works better for your users.
1. Dialog
Using Dialog to show Huawei Map and mark user home address and return user coordinate and address for further processing.
Let’s begin with coding part without wasting more time.
Step 1: Dialog layout design
Design the layout for Huawei Map to display inside Dialog.
Code:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:alpha="0.4"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:background="@color/white"
android:orientation="vertical">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapFragment"
android:name="com.huawei.hms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:layout_weight="2"
map:cameraZoom="10"
map:cameraTargetLat="24.774265"
map:cameraTargetLng="46.738586"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_close_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="closeDialog"
android:text="Close" />
<Button
android:id="@+id/btn_save_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save"
android:onClick="saveDialogMap"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
How layout look like
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Step 2: Main Activity code to display Dialog
Implement OnMapReadyCallback and OnMapClickLisner
Code:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, HuaweiMap.OnMapClickListener {}
Define some variables which we use later in the code
Code:
Dialog dialog;
private HuaweiMap hmap;
private SupportMapFragment mSupportMapFragment;
private Marker mMarker;
private LatLng myLocation;
private String myAddress;
Check code for onMapRead, onMapClick for add Marker, addMarker method and finally getUserAddress.
Code:
@Override
public void onMapReady(HuaweiMap huaweiMap) {
hmap = huaweiMap;
hmap.setOnMapClickListener(this);
}
@Override
public void onMapClick(LatLng latLng) {
myLocation = latLng;
addMyMarker(myLocation);
}
public void addMyMarker(LatLng myMapPosition) {
myAddress = getMyAddress(myMapPosition);
if(mMarker != null) mMarker.remove();
mMarker = hmap.addMarker(new MarkerOptions()
.position(myMapPosition)
.draggable(true)
.icon(BitmapDescriptorFactory.defaultMarker
(BitmapDescriptorFactory.HUE_RED))
.title(myAddress));
}
public String getMyAddress(LatLng latLng) {
Geocoder geo = new Geocoder(this, Locale.getDefault());
String myAddress = "";
try {
List<Address> addresses = geo.getFromLocation(latLng.latitude, latLng.longitude, 1);
if (addresses.size() > 0) {
String cityName = addresses.get(0).getAdminArea();
String countryName = this.getResources().getConfiguration().locale.getDisplayCountry();
String address = addresses.get(0).getAddressLine(0);
myAddress = address;
Log.i("Site_Result", "countryName: " + countryName + ", CITY : " + cityName + ", Address: " + address);
}
} catch (IOException e) {
Log.i("Site_Result", "Error");
e.printStackTrace();
}
return myAddress;
}
Lastly we can show Dialog when user click on button, can close the dialog and save user location coordinates / address data for further processing.
Code:
public void showMyDailog(){
if(dialog == null){
dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dailog_map_popup);
dialog.show();
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.mapFragment);
if (fragment instanceof SupportMapFragment) {
mSupportMapFragment = (SupportMapFragment) fragment;
mSupportMapFragment.getMapAsync(this);
}
} else {
dialog.show();
}
}
public void closeDialog(View v) {
if(dialog != null){
dialog.dismiss();
}
}
public void saveDialogMap(View v) {
if(myLocation != null && myAddress != null && dialog != null){
String text = "PopupType: Dialog \nLatitude: " +myLocation.latitude + " \nLongitude: " +myLocation.longitude+ " \nAddress: " + myAddress;
textViewAddress.setText(text);
dialog.dismiss();
}
}
Step 3: Launch the Dialog
You can result of launching of Huawei Map popup using Dialog.
Note: You have notice one issue, once user open the Dialog second time Huawei Map is becoming empty and not showing any data. To solve this issue developer can either user Activity way or Fragment way. Currently Huawei Team is working to this issue for fix Huawei Map not to be Empty on Dialog.
2. Activity
You need to make separate activity and launch the activity with theme which behaves like dialog window without any title. And return some data to parent activity when we save some user location data and address for further processing.
Let’s begin with coding part without wasting more time.
Step 1: Make new Activity (HuaweiMapPopupActivity)
We need to make new Activity to show Huawei Map.
Code:
public class HuaweiMapPopupActivity extends AppCompatActivity implements OnMapReadyCallback,
HuaweiMap.OnCameraMoveStartedListener, HuaweiMap.OnCameraMoveListener, HuaweiMap.OnCameraIdleListener,
HuaweiMap.OnMyLocationButtonClickListener, HuaweiMap.OnMapClickListener {
}
Step 2: Make new theme for Huawei to show as Dialog
Define new theme for dialog in styles.xml file.
Code:
<!-- AppDialog Huawei theme. -->
<style name="AppDialogHuaweiTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:dialogTitle">false</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
</style>
Step 3: Assign theme to Activity
Go into AndroidManifest.xml file and define the newly created theme style.
Code:
<activity
android:name=".HuaweiMapPopupActivity"
android:theme="@style/AppDialogHuaweiTheme"
android:title="" />
Step 4: Design Layout for Activity of Huawei Map
Check layout design for our Activity.
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center_vertical"
android:orientation="vertical"
tools:context=".HuaweiMapPopupActivity">
<fragment
android:id="@+id/map"
android:name="com.huawei.hms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:layout_weight="2" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:layout_marginBottom="10dp"
>
<Button
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Close" />
<Button
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save" />
</LinearLayout>
</LinearLayout>
More details, you can visit https://forums.developer.huawei.com/forumPortal/en/topic/0204395191834640053
Xamarin is a popular cross platform framework to build mobile applications using .net
A number of AppGallery Connect services support many cross platform frameworks including Xamarin. Today we are going to take a look at how you can use one of these services, App Linking within your Xamarin project.
Enabling App Linking in AppGallery Connect
Create an app or use an existing app in AppGallery Connect. Click My projects, go to Grow > App Linking, and click Use now on the displayed page.
On the displayed App Linking page, click the URL prefixes tab and then click New URL prefix to create a unique URL prefix.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Preparing the Xamarin Android Development EnvironmentCompleting Android SetupDownload the JSON file from AppGallery Connect and copy the file to your project’s Assets directory.
Set a package name. Right-click your project and choose Properties. Click Android Manifest on the displayed page and set the same package name to that in the JSON file.
Implement LazyInputStream to read the agconnect-services.json file.
Right-click your project, and choose Add > New Item. In the displayed window, select Class and name the new class HmsLazyInputStream.cs.
Implement LazyInputStream to read the agconnect-services.json file.
Right-click your project, and choose Add > New Item. In the displayed window, select Class and name the new class HmsLazyInputStream.cs.
C-like:
using System;
using System.IO;
using Android.Content;
using Android.Util;
using Huawei.Agconnect.Config;
namespace AppLinking1
{
public class HmsLazyInputStream : LazyInputStream
{
public HmsLazyInputStream(Context context)
: base(context)
{
}
public override Stream Get(Context context)
{
try
{
return context.Assets.Open("agconnect-services.json");
}
catch (Exception e)
{
Log.Error("Hms", $"Failed to get input stream" + e.Message);
return null;
}
}
}
}
Create another new class as described in the preceding steps and read the agconnect-services.json file before your app is launched. You can name the new class CustomContentProvider.cs, which extends the ContentProvider class, and set the authorities and InitOrder attributes for the new class.
C-like:
using System;
using Android.Content;
using Android.Database;
using Huawei.Agconnect.Config;
namespace AppLinking1
{
[ContentProvider(new string[] { "com.huawei.applinkingdemo.CustomContentProvider" }, InitOrder = 99)]
class CustomContentProvider : ContentProvider
{
public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)
{
throw new NotImplementedException();
}
public override string GetType(Android.Net.Uri uri)
{
throw new NotImplementedException();
}
public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
{
throw new NotImplementedException();
}
public override bool OnCreate()
{
AGConnectServicesConfig config = AGConnectServicesConfig.FromContext(Context);
config.OverlayWith(new HmsLazyInputStream(Context));
return false; throw new NotImplementedException();
}
public override ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
{
throw new NotImplementedException();
}
public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
{
throw new NotImplementedException();
}
}
}
Installing the Service SDK for AndroidRight-click your project and choose Manage NuGet Packages.
Search for AppLinking on the Browse tab. Click Xamarin.Android bindings for AGC — Applinking in the search results and install it.
Agree to the service agreement as prompted.
Developing Your AppCreating an App Linking LinkTo specify the layout of your app, open the activity_main file under Resources > layout. Sample code:
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/textDeepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DeepLink:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/deepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Link" />
<TextView
android:id="@+id/ShortLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Short Link:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textShortLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/LongLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Long Link:"
android:textSize="18sp"
android:textStyle="bold"
/>
<TextView
android:id="@+id/textLongLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/shareShort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Share Short Link" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
Open the MainActivity.cs file and import the following packages
C-like:
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using AndroidX.AppCompat.App;
using System;
using Huawei.Agconnect.Applinking;
using Uri = Android.Net.Uri;
using Debug = System.Diagnostics.Debug;
using Android.Content;
Configure button actions in the onCreate method
C-like:
FindViewById<Button>(Resource.Id.create).Click += CreateAppLink;
FindViewById<Button>(Resource.Id.shareShort).Click += ShareShortAppLink;
Create an App Linking link and implement the method for sharing the link.
C-like:
private AppLinking.Builder builder;
public static string longLink = null;
public static string shortLink = null;
public static string UriPrefix = "https://applinkingtest.drcn.agconnect.link";
public static string OpenApp_Link = "https://open.androiddemoapp.com";
public static string OpenDetail_Link = "https://open.androiddemoapp.com/detail?id=358";
private async void CreateAppLink(object sender, EventArgs e)
{
builder = new AppLinking.Builder();
// Set a URL prefix.
builder.SetUriPrefix(UriPrefix);
// Set a deep link.
builder.SetDeepLink(Uri.Parse(OpenApp_Link));
//Set the link preview type. If this method is not called, the preview page with app information is displayed by default.
builder.SetPreviewType(AppLinking.LinkingPreviewType.AppInfo);
// (Optional) Set Android link behavior.
var behaviorBuilder = new AppLinking.AndroidLinkInfo.Builder();
// Set an earliest version. If a user's app version is earlier than the earliest version, your app will redirect the user to update the app on AppGallery.
behaviorBuilder.SetMinimumVersion(1);
builder.SetAndroidLinkInfo(behaviorBuilder.Build());
longLink = builder.BuildAppLinking().Uri.ToString();
FindViewById<TextView>(Resource.Id.textLongLink).Text = longLink;
}
private void ShareShortAppLink(object sender, EventArgs e)
{
string agcLink = FindViewById<TextView>(Resource.Id.textShortLink).Text;
Intent intent = new Intent(Intent.ActionSend);
intent.SetType("text/plain");
intent.PutExtra(Intent.ExtraText, agcLink);
intent.AddFlags(ActivityFlags.NewTask);
StartActivity(intent);
}
Receiving an App Linking LinkConfigure the code of the activity for receiving an App Linking link.
Right-click the project, choose add > New Item, select Activity, and name it DetailActivity.
The sample code is as follows:
C-like:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Huawei.Agconnect.Applinking;
namespace AppLinking1
{
//[Activity(Label = "DetailActivity")]
[Activity(Name = "com.company.app.DetailActivity", Label = "DetailActivity", Theme = "@style/AppTheme")]
public class DetailActivity : Activity
{
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_detail);
// Create your app here.
try
{
//To receive links, initialize the AGConnectAppLinking instance.
AGConnectAppLinking appLinkInstance = AGConnectAppLinking.Instance;
//Call GetAppLinkingAsync() to check links of App Linking to be processed
ResolvedLinkData resolvedLinkData = await appLinkInstance.GetAppLinkingAsync(this);
String deepLink = null;
if (resolvedLinkData != null)
{
deepLink = resolvedLinkData.DeepLink.ToString();
FindViewById<TextView>(Resource.Id.deepLink).Text = deepLink;
}
}
catch (System.Exception ex)
{
FindViewById<TextView>(Resource.Id.message).Text = ex.Message;
}
}
}
}
Configure the layout for the page of receiving an App Linking link.
Right-click the project, choose add > New Item, select Android Layout, and name it activity_detail. The sample code is as follows:
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical"
tools:context=".DetailActivity">
<TextView
android:id="@+id/textDeepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DeepLink:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/deepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="message:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
Configure the Manifest file. Find the Properties directory and open the AndroidManifest file in the directory. Configure the following content in the element.
XML:
<activity android:name="com.company.app.DetailActivity" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="open.androiddemoapp.com" android:scheme="https" />
<data android:host="open.androiddemoapp.com" android:scheme="http" />
</intent-filter>
<!--App Linking SDK reads content on the clipboard each time the app is launched.-->
<meta-data android:name="com.huawei.agconnect.applinking.READ_CLIPBOARD_PERMISSION" android:value="Available" />
</activity>
Testing Your AppClick Run to test your app.
References
Getting started with Xamarin
App Linking (Android)
the app can run in huawei nova5zd, OS is HarmonyOS 2.0.0, but can't run in pixel4xl, android 13, showing "no permission", the main code is
Java:
public class TestLocationActivity extends AppCompatActivity {
public static final int LOCATION_CODE = 301;
public static final String TAG = "TestLocationActivity:wp";
private LocationManager locationManager;
private String locationProvider = null;
com.adan.gpsdemo.databinding.ActivityTestBinding activityTestBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityTestBinding = ActivityTestBinding.inflate(getLayoutInflater());
setContentView(activityTestBinding.getRoot());
getLocation();
}
private void getLocation(){
//1.获取位置管理器
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//2.获取位置提供器,GPS或是NetWork
List<String> providers = locationManager.getProviders(true);
if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS
locationProvider = LocationManager.GPS_PROVIDER;
Log.v(TAG, "定位方式GPS");
} else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是Network
locationProvider = LocationManager.NETWORK_PROVIDER;
Log.v(TAG, "定位方式Network");
}else {
Toast.makeText(this, "没有可用的位置提供器", Toast.LENGTH_SHORT).show();
return;
}
if (Build.VERSION_CODES.M <= Build.VERSION.SDK_INT) {
//获取权限(如果没有开启权限,会弹出对话框,询问是否开启权限)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);
} else {
//3.获取上次的位置,一般第一次运行,此值为null
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location!=null){
// notice textview change
showGPSValue(location.getLongitude(),location.getLatitude());
Log.v(TAG, "获取上次的位置-经纬度:"+location.getLongitude()+" "+location.getLatitude());
getAddress(location);
}else{
//监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, 3000, 1,locationListener);
}
}
} else {
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location!=null){
showGPSValue(location.getLongitude(),location.getLatitude());
Log.v(TAG, "获取上次的位置-经纬度:"+location.getLongitude()+" "+location.getLatitude());
getAddress(location);
}else{
//监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, 3000, 1,locationListener);
}
}
}
@SuppressLint("SetTextI18n")
private void showGPSValue(double longitude, double latitude){
new Thread(()->{
// 39.951111, 75.172778 change to 75°10'22''E,39°57'04''N
int hour = (int) longitude;
double minute = getDecimalValue(longitude) * 60;
double second = getDecimalValue(minute) * 60;
int hour_lat = (int) latitude;
double minute_lat = getDecimalValue(latitude) * 60;
double second_lat = getDecimalValue(minute_lat) * 60;
String strLong = hour + "°" + (int)minute + "'" + (int)second + "\"";
String strLat = hour_lat + "°" + (int)minute_lat + "'" + (int)second_lat + "\"";
Log.i(TAG,"longitude:" + strLong);
Log.i(TAG,"latitude:" + strLat);
activityTestBinding.tvGpsValue.setText(strLong + "E," + strLat + "N");
}).start();
}
/**
* get decimal of a value
* @param value double include int and decimal
* @return decimal of value
*/
private double getDecimalValue(double value){
long longPart = (long) value;
BigDecimal bigDecimal = new BigDecimal(Double.toString(value));
BigDecimal bigDecimalLongPart = new BigDecimal(Double.toString(longPart));
double dPoint = bigDecimal.subtract(bigDecimalLongPart).doubleValue();
Log.i(TAG,"DecimalValue:" + dPoint);
return dPoint;
}
public LocationListener locationListener;
{
locationListener = new LocationListener() {
// Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
@SuppressWarnings("deprecation")
@Contract(pure = true)
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
// Provider被enable时触发此函数,比如GPS被打开
@Override
public void onProviderEnabled(String provider) {
}
// Provider被disable时触发此函数,比如GPS被关闭
@Override
public void onProviderDisabled(String provider) {
}
//当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
@Override
public void onLocationChanged(Location location) {
if (location != null) {
//如果位置发生变化,重新显示地理位置经纬度
showGPSValue(location.getLongitude(),location.getLatitude());
Log.v(TAG, "监视地理位置变化-经纬度:" + location.getLongitude() + " " + location.getLatitude());
}
}
};
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == LOCATION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "申请权限", Toast.LENGTH_LONG).show();
try {
List<String> providers = locationManager.getProviders(true);
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是Network
locationProvider = LocationManager.NETWORK_PROVIDER;
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS
locationProvider = LocationManager.GPS_PROVIDER;
}
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location != null) {
showGPSValue(location.getLongitude(),location.getLatitude());
Log.v("TAG", "获取上次的位置-经纬度:" + location.getLongitude() + " " + location.getLatitude());
} else {
// 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
}
} catch (SecurityException e) {
e.printStackTrace();
}
} else {
Toast.makeText(this, "缺少权限", Toast.LENGTH_LONG).show();
finish();
}
} else {
throw new IllegalStateException("Unexpected value: " + requestCode);
}
}
//获取地址信息:城市、街道等信息
private void getAddress(Location location) {
List<Address> result;
try {
if (location != null) {
Geocoder gc = new Geocoder(this, Locale.getDefault());
result = gc.getFromLocation(location.getLatitude(),
location.getLongitude(), 1);
new Thread(()->{
String addValue = result.toString();
activityTestBinding.tvAddressValue.setText(addValue);
}).start();
Log.v(TAG, "获取地址信息:"+ result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
locationManager.removeUpdates(locationListener);
}
}
Click to expand...
Click to collapse
XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ExtraText">
<!-- 粗略的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 精确的位置权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GPSDemo">
<activity
android:name=".TestFusedLocationProviderClientActivity"
android:exported="true">
<!-- <meta-data-->
<!-- android:name="android.app.lib_name"-->
<!-- android:value="" />-->
</activity>
<activity android:name=".MainActivity"></activity>
<activity android:name=".TestGPS2"></activity>
<activity android:name=".TestLocationActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Test1" />
<activity android:name=".Test2" />
</application>
</manifest>
whloe code is
GitHub - yhm2046/GPSDemo: test gps
test gps. Contribute to yhm2046/GPSDemo development by creating an account on GitHub.
github.com
mm11751 said:
the app can run in huawei nova5zd, OS is HarmonyOS 2.0.0, but can't run in pixel4xl, android 13, showing "no permission", the main code is
XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ExtraText">
<!-- 粗略的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 精确的位置权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GPSDemo">
<activity
android:name=".TestFusedLocationProviderClientActivity"
android:exported="true">
<!-- <meta-data-->
<!-- android:name="android.app.lib_name"-->
<!-- android:value="" />-->
</activity>
<activity android:name=".MainActivity"></activity>
<activity android:name=".TestGPS2"></activity>
<activity android:name=".TestLocationActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Test1" />
<activity android:name=".Test2" />
</application>
</manifest>
whloe code is
GitHub - yhm2046/GPSDemo: test gps
test gps. Contribute to yhm2046/GPSDemo development by creating an account on GitHub.
github.com
Click to expand...
Click to collapse
Most likely because Android 13 includes behavior changes that may affect your app. The following behavior changes apply exclusively to apps that are targeting Android 13 or higher.
Privacy
Granular media permissions
Use of body sensors in the background requires new permission
Performance and battery
User experience
App color theme applied automatically to WebView content
Google Play services
Updated non-SDK restrictions
rodken said:
Most likely because Android 13 includes behavior changes that may affect your app. The following behavior changes apply exclusively to apps that are targeting Android 13 or higher.
Privacy
Granular media permissions
Use of body sensors in the background requires new permission
Performance and battery
User experience
App color theme applied automatically to WebView content
Google Play services
Updated non-SDK restrictions
Click to expand...
Click to collapse
I modify some code , but sitll don't work. Now how can I do ?
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
mm11751 said:
I modify some code , but sitll don't work. Now how can I do ?
Click to expand...
Click to collapse
Try API Level 33.
rodken said:
Try API Level 33.
Click to expand...
Click to collapse
I modified this code, still no work
mm11751 said:
I modified this code, still no work
Click to expand...
Click to collapse
Are you the developer of the app?
rodken said:
Are you the developer of the app?
Click to expand...
Click to collapse
yes, I wrote it
mm11751 said:
yes, I wrote it
Click to expand...
Click to collapse
You might want to redirect your question(s) to this forum to receive more than one insight on the issue.