question

MathewPotrykus-8802 avatar image
0 Votes"
MathewPotrykus-8802 asked MathewPotrykus-8802 commented

My App won't Finish or return data

I have two apps App 1 and App 2
https://github.com/Mathew-Potrykus/App1
https://github.com/Mathew-Potrykus/App2
App 1 calls App 2 and passes through some string data that App 2 will use to get a list of Assets, upon selected an asset from the list you go into the details of that asset and can press the 'Submit' button which should then return that asset's details back to App 1.
App 1 is an Android Studio Java app
App 2 is an Xamarin.Forms c# app

My Issue:
Everything but the final step is working as intended;
App 1 opens App 2
App 2 reads the string data and compiles a list
An item is selected in the list and the Details Page is shown
The Submit button is pressed
-------------------------------------------------------------
This is the part that does not work
-------------------------------------------------------------
Close App 2 and send the asset details back to App 1

The line of code that is not working is in my MainActivity on Line 50, 'Finish()'.
It does not close the app or end the process so that the result can return to App 1.
I have noticed that on the rare occasion, the 'Finish()' WILL work but ONLY on the first time when the app was started. Any other attempts that open the app again after that first one do nothing.
There is also the issue that when it DOES get back to App 1, the Result Code is 'Cancelled' and the Intent Data is null

Below is the code for the important parts and that are relvant to the process of getting the data back and forth.
If more code is needed to help figure this out, please let me know, I've been stuck on this for weeks now.

App 2 - Splash Activity - Android

 namespace AssetApp.Droid.Activities
 {
  [Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
  public class SplashActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
  {
  #region Variables
  static readonly string TAG = "X:" + typeof(SplashActivity).Name;
  public static bool isConnected;
  static PermissionsHandler permissionHandler;
  #endregion
    
  protected override void OnCreate(Bundle savedInstanceState)
  {
  base.OnCreate(savedInstanceState);
  // Initialize Xamarin.Essentails
  Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    
  Startup();
  // Test intent return - Worked!
  //TestReturn();
  }
    
  //public void ReturnToCaller(SendAsset assetDetails)
  //{
  // Intent returnAsset = new Intent();
    
  // returnAsset.PutExtra("ID", assetDetails.ID);
  // returnAsset.PutExtra("AssetNumber", assetDetails.Code);
  // returnAsset.PutExtra("Description", assetDetails.Description);
  // returnAsset.PutExtra("Barcode", assetDetails.Barcode);
  // returnAsset.PutExtra("Serial", assetDetails.Serial);
  // SetResult(Result.Ok, returnAsset);
  // Finish();
  //}
    
  //public void TestReturn()
  //{
  // Intent intent = new Intent();
  // intent.PutExtra("ID", "This worked!");
  // SetResult(Result.Ok, intent);
  // Finish();
  //}
    
  async void Startup()
  {
    
  var appSettings = new ApplicationSettings(new ConfigurationFileProvider());
  var appCenterKey = appSettings.AppCenterKey;
  // Attach the appcenter logging
  AppCenter.Start(appCenterKey, typeof(Analytics), typeof(Crashes));
    
  // Permission Request
  permissionHandler = new PermissionsHandler();
  await permissionHandler.GetCameraPermissionAsync();
  await permissionHandler.GetNetworkStatePermissionAsync();
  await permissionHandler.GetPhonePermissionAsync();
  await permissionHandler.GetStorageWritePermissionAsync();
  await permissionHandler.GetStorageReadPermissionAsync();
    
  Globals.ApiBaseUrl = appSettings.ApiBaseUrl;
    
  // Grab variables passed from caller App
  Globals.userID = Intent.GetStringExtra("UserID");
  Globals.locationID = Intent.GetStringExtra("LocationID");
  Globals.taskID = Intent.GetStringExtra("TaskID");
  Globals.deviceID = Intent.GetStringExtra("DeviceID");
    
  // Call database setup
  DatabaseStuff();
  }
    
  async void DatabaseStuff()
  {
  /*
                 Calls to API to load data using received details from caller app....
             */
  // Load the MainActivity which will decide whether to display the MainPage or the AccessDeniedPage
  Intent main = new Intent(Application.Context, typeof(MainActivity))
  StartActivity(main);
  }
    
  public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
  {
  Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
  base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
  }
    
  }
 }


App 2 - Main Activity - Android

 namespace AssetApp.Droid
 {
  [Activity(Label = "@string/ApplicationName", Theme = "@style/MainTheme", LaunchMode = LaunchMode.SingleTop)]
  public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
  {
  protected override void OnCreate(Bundle savedInstanceState)
  {
  base.OnCreate(savedInstanceState);
    
  TabLayoutResource = Resource.Layout.Tabbar;
  ToolbarResource = Resource.Layout.Toolbar;
  Xamarin.Essentials.Platform.Init(this, savedInstanceState);
  global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
  ZXing.Net.Mobile.Forms.Android.Platform.Init();
    
  ReturnHelper.SetReturn(Return);
    
  LoadApplication(new App());
    
  CreateNotificationFromIntent(Intent);
  }
    
  public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
  {
  Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
  global::ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
  base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
  }
            
  protected override void OnNewIntent(Intent intent)
  {
  CreateNotificationFromIntent(intent);
  }
    
  void CreateNotificationFromIntent(Intent intent)
  {
  if (intent?.Extras != null)
  {
  string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
  string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
  DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
  }
  }
    
  public void Return(string assetId)
  {
  var intent = new Intent();
  intent.PutExtra("ID", assetId);
  SetResult(Result.Ok, intent);
  Finish();
  }
    
  }
 }

App 2 - Return Helper - Forms

 namespace AssetApp.Utils
 {
  public static class ReturnHelper
  {
  public static Action<string> Return { get; internal set; }
    
  public static void SetReturn(Action<string> returnMethod)
  {
  if (Return == null)
  {
  Return = returnMethod;
  }
  }
  }
 }

App 2 - Details Page - Forms
(Button Function)

 private async void SubmitChanges(object sender, EventArgs args)
 {
  // Convert ViewModel to SendModel
  SendAsset asset = new SendAsset(_updatedAsset);
  // return selected asset
  //MessagingCenter.Send<DetailsPage, SendAsset>(this, "Asset", asset);
  // Return back to Main Page
  await Navigation.PopToRootAsync();
     // Pass data through to Android to Finish and return to caller
  ReturnHelper.Return("id");
 }

App 1 - Main Activity - Android

 public void CallApp() {
  Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.AssetApp");
  // Check if there is an app that can be opened
  if (launchIntent != null) {
  // Add variables
  launchIntent.putExtra("LocationID", "locationID");
  launchIntent.putExtra("TaskID", "taskID");
  launchIntent.putExtra("UserID", "userID");
  launchIntent.putExtra("DeviceID", "deviceID");
  launchIntent.setFlags(0);
  launchIntent.setType("text/plain");
  launchIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
  mStartForResult.launch(launchIntent);
  }
 }
    
 ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
  @Override
  public void onActivityResult(ActivityResult result) {
  if (result.getResultCode() == Activity.RESULT_OK) {
  Intent intent = result.getData();
  if (intent != null) {
  String thing1 = intent.getStringExtra("ID");
  Toast.makeText(MainActivity.this, thing1, Toast.LENGTH_SHORT).show();
  }
  }
  }
 });
dotnet-xamarin
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @MathewPotrykus-8802 ,when you come back from app2, will the method onActivityResult in App1 be triggered?

Besides, what's the PermissionsHandler and ConfigurationFileProvider? If it is convenient for you,could you please post a basic demo to github or onedriver so that we can try to reproduce this problem on our side?

0 Votes 0 ·

As long as the app finishes it's lifecycle then yes it does hit the onActivityResult. If you notice, on Line 20 and 36 of the SplashActivity, instead of running through the rest of the app process it immediately returns a test value and this successfully returns to App 1 as well as giving the correct Result Code and containing the Intent Data provided.
However with Line 20 removed because the Finish only tends to work the first time this usually only gets hit when I manually close App 2 or stop debugging.
I have some stripped down test apps that I created to make sure I could replicate the issue, I will work on getting that into a github today.


0 Votes 0 ·

Could you please post your app’s link after posting your app to github?

0 Votes 0 ·
Show more comments

@JessieZhang-2116
Has there been any investigation into this?
I'm still stuck on this problem

0 Votes 0 ·

0 Answers