Home Blog

Threat-Primarily based Testing: Knowledgeable Information


Why must you care about threat primarily based testing?

That what I will cowl right here, why? As a result of I am being informed by many testing consultants on my podcasts that they always wrestle with fast-paced software program improvement.

This reveals me that testing groups face an inconceivable problem: complete testing with restricted time and assets. You’ve hundreds of check circumstances, tight deadlines, and stakeholders demanding each pace and high quality.

The query is not whether or not you may check every thing—it is the way you resolve what to check first.

That is the place risk-based testing transforms your method from reactive to strategic.

Drawing from real-world insights of testing consultants Bob Crews and Jean Ann Harrison shared at our annual Automation Guild convention, this information reveals learn how to implement risk-based testing that really works in follow.

What’s Threat-Primarily based Testing?

Threat-based testing is a technique that prioritizes check execution primarily based on the potential threat of failure and the affect of that failure on customers and enterprise operations.

As Bob Crews places it: “When you have 1,000 check circumstances and restricted time, how do you choose which to execute? That is what risk-based testing helps reply.”

In contrast to conventional testing approaches that deal with all options equally, risk-based testing focuses your restricted time and assets the place they matter most—on high-risk areas of the software program.

It is a structured method to threat evaluation that adapts your testing technique to product complexity, launch timelines, and enterprise criticality.

Strive our Free Threat-Primarily based Testing Calculator

The Core Precept

Keep in mind, not all software program elements carry equal threat.

A beauty bug in a rarely-used admin panel poses minimal menace to your online business, whereas a cost processing failure might price hundreds of {dollars} per hour and harm buyer belief completely.

Threat-based testing acknowledges this actuality and supplies a framework for making clever selections about the place to focus testing efforts.

Why Threat-Primarily based Testing Works in Actual Tasks

Jean Ann Harrison’s in depth expertise in regulated industries, together with medical units and wearable tech, demonstrates that threat administration is not simply concept—it is important follow. “Each launch features a reassessed threat desk,” she explains. “You monitor affect, probability, and mitigation—not simply bugs.”

Actual-World Advantages

  1. Prioritized Testing Efforts Threat-based testing matches the extent of check effort to the extent of threat, making certain higher-risk objects obtain extra thorough testing. As Bob Crews emphasizes: “It isn’t nearly protection—it is about worth.”
  2. Elevated Software program High quality By specializing in high-risk areas, groups forestall essential failures earlier than they occur. This method helps establish essential defects early within the improvement lifecycle and ensures thorough testing of vital capabilities.
  3. Higher Stakeholder Communication Threat scoring helps justify testing selections to enterprise and product groups. It supplies a framework for clear communication about dangers in language all stakeholders perceive.
  4. Enhanced Threat Visibility Groups do not simply establish threat—they make it seen, actionable, and trackable all through the check course of.

Test Management Machine Learning Robot

How you can Carry out Threat Evaluation in Software program Testing

Efficient threat evaluation entails figuring out potential dangers and assigning affect and probability scores to prioritize testing efforts systematically.

Bob Crews’ Threat Scoring Formulation

Bob Crews has developed a sensible system for calculating chance scores:

Likelihood = ((Complexity × 3) + (Frequency × 2) + Newness) ÷ 3

This system weights elements primarily based on their significance in predicting failure probability:

  • Complexity (Weight 3): Complicated elements statistically comprise extra defects
  • Frequency (Weight 2): Continuously used elements have greater publicity to failure
  • Newness (Weight 1): New performance carries inherent threat

For every issue, use a easy 1-3 scale:

  1. Low (easy, rare, or mature)
  2. Medium (reasonable complexity, utilization, or newness)
  3. Excessive (complicated, frequent, or fully new)

Influence Evaluation

Individually assess affect utilizing a 0-10 scale:

  • 0-2: Minimal affect, beauty points solely
  • 3-4: Minor operational affect with workarounds obtainable
  • 5-6: Vital affect on consumer expertise or enterprise operations
  • 7-8: Main affect affecting essential enterprise processes
  • 9-10: Catastrophic affect threatening enterprise viability

Chat About Threat in our Neighborhood

Closing Threat Rating = Likelihood × Influence

Sorts of Threat to Think about

Jean Ann Harrison frames threat evaluation by actual penalties:

  • Reputational Threat: Injury to model repute and buyer belief
  • Compliance Threat: Failing regulatory audits (e.g., FDA compliance)
  • Bodily Hurt: Security dangers in methods like robotic surgical procedure
  • Enterprise Disruption: Operational failures affecting income
  • Safety Threat: Information breaches and unauthorized entry

She encourages testers to ask: “Who could possibly be harmed, how badly, and the way seemingly is it?”

How you can Prioritize Testing Efforts Primarily based on Threat

As soon as you have calculated threat scores, plot elements on a threat quadrant to visualise and defend check priorities:

The 4-Quadrant Strategy

  • Quadrant 4 (Excessive Influence, Excessive Likelihood): Check first with complete protection
  • Quadrant 3 (Excessive Influence, Low Likelihood): Check second, specializing in high-impact eventualities
  • Quadrant 2 (Excessive Likelihood, Low Influence): Check third with automated or primary checks
  • Quadrant 1 (Low Influence, Low Likelihood): Check final or defer if time is constrained

This framework helps testing groups make quick, defensible selections, particularly below time constraints.

Threat-Primarily based Testing Strategies That Truly Work

Visible Threat Mapping

Create warmth maps displaying threat ranges throughout system elements utilizing colour coding—purple for high-risk areas, yellow for medium-risk, and inexperienced for low-risk.

These visible instruments function highly effective communication aids for stakeholders.

Collaborative Threat Scoring

Bob Crews advocates for team-based threat evaluation periods: “Get the crew collectively… give every particular person 5 seconds to carry up a rating card for affect, then for chance, common the rating, compute the chance rating.”

This method combines particular person experience with group validation, typically reaching 90% consensus on threat scores.

Threat-Primarily based Check Automation

Prioritize check automation primarily based on threat scores moderately than technical ease of automation.

Excessive-risk, incessantly executed check circumstances ought to obtain automation precedence even when they require extra complicated implementation.

Steady Threat Reassessment

Threat profiles change as improvement progresses. Repeatedly reassess dangers primarily based on:

  • New defects found throughout testing
  • Adjustments in necessities or enterprise priorities
  • Suggestions from stakeholders or customers
  • Efficiency knowledge from manufacturing methods

Threat-Primarily based Testing in Agile Environments

Threat-based testing adapts effectively to agile methodologies when correctly carried out.

Dash-Degree Implementation

Bob Crews applies risk-based testing in agile sprints by “figuring out high-risk tales and attaching exploratory periods to them.” This method entails:

  • Story Threat Scoring: Assign threat scores to consumer tales throughout dash planning
  • Threat-Primarily based Prioritization: Use threat scores alongside enterprise worth for story prioritization
  • Every day Threat Monitoring: Embody threat standing updates in day by day standups
  • Dash Retrospective Opinions: Consider threat evaluation effectiveness

Stakeholder Involvement

Jean Ann Harrison emphasizes: “So long as testers are on the desk to speak threat, you are doing it proper.”

Threat-based testing helps shift conversations from “what can we check?” to “what ought to we check, and why?”

 

Perf Calculator

How you can Talk Threat With out Worry

Efficient threat communication is essential for achievement. Jean Ann Harrison shares a cautionary story of a check lead who failed to speak recognized threat, leading to a two-week undertaking delay.

Finest Practices for Threat Communication

  1. Body Threat as High quality Assurance Harrison’s philosophy: “Threat conversations aren’t confrontations. They’re a part of high quality.”
  2. Select the Proper Timing Think about the recipient’s way of thinking and willingness to hear when speaking dangers.
  3. Begin Small Use brown bag lunches or dash evaluations to debate potential dangers earlier than they turn out to be essential.
  4. Deal with Prevention Harrison emphasizes: “I at all times look to stop unhealthy issues from taking place, and fairly frankly, that is high quality assurance.”

Business-Particular Functions

Medical Gadgets and Healthcare

In life-critical purposes, affected person security overrides all different threat elements. Jean Ann Harrison notes: “I began actually fascinated with individuals might truly get damage with the system I used to be engaged on.”

Medical system threat evaluation should think about:

  • FDA compliance necessities
  • Scientific threat eventualities
  • Validation in healthcare environments
  • Affected person security as the first concern

Monetary Companies

Monetary purposes require give attention to:

  • Regulatory compliance (SOX, PCI DSS, GDPR)
  • Transaction integrity and audit trails
  • Actual-time processing dangers
  • Safety and fraud prevention

E-commerce and Retail

E-commerce threat evaluation emphasizes:

  • Income affect of failures
  • Buyer expertise dangers
  • Peak load and seasonal concerns
  • Fee processing safety

Widespread Errors to Keep away from

Over-Engineering the Course of

Preserve threat evaluation easy and sensible. If threat evaluation takes longer than 10 minutes per element, the method might be too complicated.

Static Threat Evaluation

Threat profiles change all through improvement. Failing to replace assessments results in misaligned priorities.

Ignoring Stakeholder Enter

Technical groups conducting threat evaluation in isolation typically miss essential enterprise context.

Treating Threat-Primarily based Testing as Threat Avoidance

The purpose is threat administration, not threat elimination. Deal with making knowledgeable selections about which dangers to handle, settle for, or monitor.

Be a part of our Free Coaching Periods

Measuring Success in Threat-Primarily based Testing

Monitor effectiveness by key metrics:

Threat-Centered Metrics

  • Threat Protection Share: Share of high-risk elements adequately examined
  • Important Defects per Check Hour: Effectivity of discovering high-severity points
  • Threat Mitigation Price: Share of recognized dangers adequately addressed

Enterprise Influence Metrics

  • Manufacturing Failure Prevention: Discount in essential manufacturing incidents
  • Stakeholder Confidence Scores: Satisfaction with threat communication and administration
  • Time-to-Market Enhancements: Quicker, extra assured launch selections

Running Automation Robot Doctor

Getting Began: Your Threat-Primarily based Testing Motion Plan

Step 1: Construct Your Asset Stock

Create a complete record of elements requiring threat evaluation, together with necessities, consumer tales, system elements, and integration factors.

Step 2: Conduct Preliminary Threat Evaluation

Use Bob Crews’ system to attain chance and assess affect for every element.

Step 3: Plot and Prioritize

Create threat quadrants and prioritize testing efforts primarily based on threat scores.

Step 4: Design Threat-Pushed Check Technique

Allocate assets primarily based on threat ranges, with skilled testers specializing in high-risk areas.

Step 5: Execute and Monitor

Start with highest-risk elements and constantly monitor for altering threat profiles.

Threat Primarily based Instruments and Assets

Free Threat Scoring Calculator

To implement these knowledgeable methodologies, use TestGuild’s free Threat Scoring Calculator that automates Bob Crews’ confirmed system and supplies visible threat quadrant mapping.

Check Administration Integration

Trendy check administration instruments like ALM, QTest, and TestRail provide risk-based testing capabilities together with customized threat fields, risk-based prioritization, and protection reporting.

The Way forward for Threat-Primarily based Testing

Threat-based testing continues evolving with rising applied sciences:

AI and Machine Studying Integration

  • Automated threat evaluation primarily based on code complexity and historic patterns
  • Predictive threat analytics for proactive mitigation
  • Dynamic threat adjustment as new info emerges

DevOps and Steady Supply

  • Threat-aware deployment pipelines
  • Steady threat monitoring in manufacturing
  • Threat-based function flag methods

Use Threat Primarily based Testing To Rework Your Testing Technique

Threat-based testing represents a elementary shift towards strategic, value-driven high quality assurance.

The insights from consultants Bob Crews and Jean Ann Harrison reveal that this method delivers measurable enhancements in testing effectiveness and enterprise outcomes.

Success lies not in good threat evaluation, however in constant utility of systematic approaches that enhance decision-making below uncertainty. Whether or not you are simply starting to discover risk-based testing or seeking to mature present practices, the ideas and strategies on this information present a basis for reworking your testing method.

Begin your risk-based testing journey as we speak by implementing Bob Crews’ chance system and Jean Ann Harrison’s prevention-focused mindset. Deal with making threat seen, actionable, and trackable all through your testing course of.

Keep in mind: Threat does not need to be scary—it simply needs to be seen.

ios – Learn how to apply non-uniform scaling to a rotated UIView (rectangle) over Mapbox with out distortion?


I’m making an attempt to permit non-uniform scaling (horizontal or vertical) of a UIView rectangle that’s positioned over a Mapbox mapView and has already been rotated. Uniform scaling works properly, however once I try to use non-uniform scaling (scaling solely X or Y) utilizing transforms after rotation, the rectangle turns into distorted like a parallelogram.

To keep away from distortion, I as an alternative redraw the rectangle utilizing coordinate math on the finish of the gesture, however this makes the scaling really feel abrupt and never clean. I need to obtain clean, stay non-uniform scaling after rotation with out visible distortion. I’ve tried utilizing rework.scaledBy(x:y:), however it doesn’t preserve the rectangle’s orthogonality post-rotation.

How can I obtain clean, interactive, non-uniform scaling on a rotated view with out it deforming?

Code Snippets

Right here’s the pinchProcess gesture handler:

@objc func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
    guard isScalingEnabled, let targetView = self.scalingView else { return }

    if recognizer.state == .started {
        previousScale = 1.0
        initialPinchLocation = recognizer.location(in: targetView)
    }

    if recognizer.state == .ended || recognizer.state == .cancelled {
        if hasRotationApplied {
            gestureDelegate?.applyScalingAndRedraw(for: targetView, axis: lastScaleAxis, scaleFactor: finalScaleValue)
        } else {
            gestureDelegate?.finalizeSnap(for: targetView, usingPoints: originalPoints)
        }
        return
    }

    if recognizer.numberOfTouches < 2 {
        initialPinchLocation = recognizer.location(in: targetView)
        return
    }

    let touchPointA = recognizer.location(ofTouch: 0, in: targetView)
    let touchPointB = recognizer.location(ofTouch: 1, in: targetView)
    lastScaleAxis = detectScaleAxis(from: touchPointA, to: touchPointB, basedOn: originalPoints)

    let scaleFactor = recognizer.scale / previousScale
    let xDiff = originalPoints[1].x - originalPoints[0].x
    let yDiff = originalPoints[1].y - originalPoints[0].y

    if xDiff == 0 || yDiff == 0 {
        hasRotationApplied = false

        change detectGestureDirection(touchPointA, point2: touchPointB) {
        case "V":
            targetView.rework = targetView.rework.scaledBy(x: 1, y: scaleFactor)
        case "H":
            targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: 1)
        default:
            targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: scaleFactor)
        }

        previousScale = recognizer.scale
    } else {
        finalScaleValue = recognizer.scale
        hasRotationApplied = true
        targetView.rework = targetView.rework.scaledBy(x: scaleFactor, y: scaleFactor)
    }

    previousScale = recognizer.scale
}
func applyScalingAndRedraw(for view: UIView, axis: String, scaleFactor: CGFloat) {
    // Computes new factors primarily based on the scaling axis and applies redraw logic
    // Geometry strategies replace coordinates and redraw the rectangle accurately
}

ChatGPT helps velocity up affected person screening for medical trials – NanoApps Medical – Official web site


A brand new examine within the tutorial journal Machine Studying: Well being discovers that ChatGPT can speed up affected person screening for medical trials, exhibiting promise in decreasing delays and bettering trial success charges.

Researchers at UT Southwestern Medical Centre used ChatGPT to evaluate whether or not sufferers have been eligible to participate in medical trials and have been in a position to determine appropriate candidates inside minutes.

Scientific trials, which take a look at new drugs and procedures on the general public, are very important for creating and validating new therapies. However many trials battle to enrol sufficient members. In keeping with a current examine, as much as 20% of Nationwide Most cancers Institute (NCI)-affiliated trials fail as a result of low enrolment. This not solely inflates prices and delays outcomes, but in addition undermines the reliability of latest therapies.

At the moment, screening sufferers for trials is a guide course of. Researchers should evaluate every affected person’s medical information to find out in the event that they meet eligibility standards, which takes round 40 minutes per affected person. With restricted workers and sources, this course of is usually too sluggish to maintain up with demand.

A part of the issue is that precious affected person data contained in digital well being information (EHRs) is usually buried in unstructured textual content, similar to medical doctors’ notes, which conventional machine studying software program struggles to decipher. Consequently, many eligible sufferers are neglected as a result of there merely isn’t sufficient capability to evaluate each case. This contributes to low enrolment charges, trial delays and even cancellations, finally slowing down entry to new therapies.

To counter this downside, the researchers have checked out methods of rushing up the screening course of by utilizing ChatGPT. Researchers used GPT-3.5 and GPT-4 to analyse 74 sufferers’ information to see in the event that they certified for a head and neck most cancers trial.

3 ways of prompting the AI have been examined:

  • Structured Output (SO): asking for solutions in a set format.
  • Chain of Thought (CoT): asking the mannequin to elucidate its reasoning.
  • Self-Uncover (SD): letting the mannequin work out what to search for.

The outcomes have been promising. GPT-4 was extra correct than GPT-3.5, although barely slower and costlier. Screening occasions ranged from 1.4 to 12.4 minutes per affected person, with prices between $0.02 and $0.27.

LLMs like GPT-4 may help display sufferers for medical trials, particularly when utilizing versatile standards. They’re not good, particularly when all guidelines should be met, however they’ll save time and help human reviewers.”

Dr. Mike Dohopolski, lead writer of the examine

This analysis highlights the potential for AI to help quicker, extra environment friendly medical trials – bringing new therapies to sufferers sooner.

The examine is without doubt one of the first articles printed in IOP Publishing’s Machine Studying collection™, the world’s first open entry journal collection devoted to the appliance and growth of machine studying (ML) and synthetic intelligence (AI) for the sciences.

The identical analysis workforce have labored on a technique that permits surgeons to regulate sufferers’ radiation remedy in actual time while they’re nonetheless on the desk. Utilizing a deep studying system known as GeoDL, the AI delivers exact 3D dose estimates from CT scans and therapy information in simply 35 milliseconds. This might make adaptive radiotherapy quicker and extra environment friendly in actual medical settings.

Supply:

Journal reference:

Beattie, J., et al. (2025). ChatGPT augmented medical trial screening. Machine Studying: Well beingdoi.org/10.1088/3049-477x/adbd47.

ios – xcode run kotlin multiplatform mission can’t set up iosApp on IPhone16


Xcode run kotlin multiplatform mission to put in iosApp on IPhone16, tips on how to mounted it ?

I had obtain a clean kmp mission , and put in efficiently on IPhone16. After putting in the iOS app on an actual machine (iPhone 15), it was instantly uninstalled. Xcode reported the error proven within the screenshot.

and it may be archived to AppStore.

enter image description here

无法安装“KotlinAppProject”
Area: IXUserPresentableErrorDomain
Code: 1
Restoration Suggestion: Software is lacking the application-identifier entitlement.
Person Data: {
    DVTErrorCreationDateKey = "2025-08-03 11:32:01 +0000";
    IDERunOperationFailingWorker = IDEInstallCoreDeviceWorker;
}
--
Failed to put in the app on the machine.
Area: com.apple.dt.CoreDeviceError
Code: 3002
Person Data: {
    NSURL = "file:///Customers/HOX4SGH/Library/Developer/Xcode/DerivedData/iosApp-gbaojemzkfyvhrbgladtchqcvlfq/Construct/Merchandise/Debug-iphoneos/KotlinAppProject.app";
}
--
无法安装“KotlinAppProject”
Area: IXUserPresentableErrorDomain
Code: 1
Failure Cause: 请稍后再试。
Restoration Suggestion: Software is lacking the application-identifier entitlement.
--
Software is lacking the application-identifier entitlement.
Area: MIInstallerErrorDomain
Code: 63
Person Data: {
    FunctionName = "-[MIInstallableBundle _validateApplicationIdentifierForNewBundleSigningInfo:error:]";
    LegacyErrorString = ApplicationVerificationFailed;
    SourceFileLine = 1130;
}
--

Occasion Metadata: com.apple.dt.IDERunOperationWorkerFinished : {
    "device_identifier" = "00008140-000435313CF2801C";
    "device_isCoreDevice" = 1;
    "device_model" = "iPhone17,3";
    "device_osBuild" = "18.5 (22F76)";
    "device_platform" = "com.apple.platform.iphoneos";
    "device_thinningType" = "iPhone17,3";
    "dvt_coredevice_version" = "443.24";
    "dvt_coresimulator_version" = "1010.15";
    "dvt_mobiledevice_version" = "1784.120.3";
    "launchSession_schemeCommand" = Run;
    "launchSession_state" = 1;
    "launchSession_targetArch" = arm64;
    "operation_duration_ms" = 5069;
    "operation_errorCode" = 1;
    "operation_errorDomain" = IXUserPresentableErrorDomain;
    "operation_errorWorker" = IDEInstallCoreDeviceWorker;
    "operation_name" = IDERunOperationWorkerGroup;
    "param_debugger_attachToExtensions" = 0;
    "param_debugger_attachToXPC" = 1;
    "param_debugger_type" = 3;
    "param_destination_isProxy" = 0;
    "param_destination_platform" = "com.apple.platform.iphoneos";
    "param_diag_113575882_enable" = 0;
    "param_diag_MainThreadChecker_stopOnIssue" = 0;
    "param_diag_MallocStackLogging_enableDuringAttach" = 0;
    "param_diag_MallocStackLogging_enableForXPC" = 1;
    "param_diag_allowLocationSimulation" = 1;
    "param_diag_checker_tpc_enable" = 1;
    "param_diag_gpu_frameCapture_enable" = 0;
    "param_diag_gpu_shaderValidation_enable" = 0;
    "param_diag_gpu_validation_enable" = 0;
    "param_diag_guardMalloc_enable" = 0;
    "param_diag_memoryGraphOnResourceException" = 0;
    "param_diag_mtc_enable" = 1;
    "param_diag_queueDebugging_enable" = 1;
    "param_diag_runtimeProfile_generate" = 0;
    "param_diag_sanitizer_asan_enable" = 0;
    "param_diag_sanitizer_tsan_enable" = 0;
    "param_diag_sanitizer_tsan_stopOnIssue" = 0;
    "param_diag_sanitizer_ubsan_enable" = 0;
    "param_diag_sanitizer_ubsan_stopOnIssue" = 0;
    "param_diag_showNonLocalizedStrings" = 0;
    "param_diag_viewDebugging_enabled" = 1;
    "param_diag_viewDebugging_insertDylibOnLaunch" = 1;
    "param_install_style" = 2;
    "param_launcher_UID" = 2;
    "param_launcher_allowDeviceSensorReplayData" = 0;
    "param_launcher_kind" = 0;
    "param_launcher_style" = 99;
    "param_launcher_substyle" = 0;
    "param_runnable_appExtensionHostRunMode" = 0;
    "param_runnable_productType" = "com.apple.product-type.software";
    "param_structuredConsoleMode" = 1;
    "param_testing_launchedForTesting" = 0;
    "param_testing_suppressSimulatorApp" = 0;
    "param_testing_usingCLI" = 0;
    "sdk_canonicalName" = "iphoneos18.5";
    "sdk_osVersion" = "18.5";
    "sdk_variant" = iphoneos;
}
--


System Data

macOS Model 15.5 (Construct 24F74)
Xcode 16.4 (23792) (Construct 16F6)
Timestamp: 2025-08-03T19:32:01+08:00

Flutter iOS app UI proven on startup earlier than splash


I’m constructing an app for ios/android utilizing flutter. When the app begins, the move is:

important.dart
native splash displaying dev emblem (throughout which app begin up occurs)
authgate
app widget (extracted this from important to cut back how a lot work important was doing)
flutter splash displaying app emblem (throughout which permissions are referred to as)
touchdown display screen

The problem I’m seeing is when the iOS app begins, it briefly flashes the final seen UI display screen BEFORE the native splash display screen. e.g. If I used to be viewing the settings display screen within the app then stop the app, subsequent time I begin the app, the very first thing I see earlier than the native splash display screen is a flash of the settings display screen.

I simply wished to know if anybody has skilled that earlier than, and the way they resolved it.

I’ve googled for hours and can’t discover something related, nor can I discover something in flutter documentation. It appears I’ve managed to do one thing in begin up that created this challenge that nobody else will get? It’s driving me insane. On condition that this happens previous to native splash, I assume it’s a snapshot specific to iOS because it doesn’t occur within the android app, and whereas it’s not a breaking challenge, it doesn’t look nice from a consumer perspective.

I’ve tried including a white background to cover snapshot, as an alternative I received native splash then white display screen then native splash once more so eliminated the white background.
Added UIApplication.shared.ignoreSnapshotOnNextApplicationLaunch() to AppDelegate with no change in behaviour

1. Most important.dart

Future important() async {
  WidgetsFlutterBinding.ensureInitialized();
  tz.initializeTimeZones();
  await Future.delayed(const Period(seconds: 2));

  await Firebase.initializeApp(choices: DefaultFirebaseOptions.currentPlatform);
  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
  ]);

  await Hive.initFlutter();
  Hive.registerAdapter(MedicationAdapter());  // TypeID 0
  Hive.registerAdapter(DoseEntryAdapter()); // TypeID 1
  Hive.registerAdapter(HealthProfessionalAdapter()); // TypeID 2
  Hive.registerAdapter(DiscussionItemAdapter()); // TypeID 3
  Hive.registerAdapter(AppointmentAdapter()); // TypeID 4
  Hive.registerAdapter(UserProfileAdapter()); // TypeID 5
  Hive.registerAdapter(TodoItemAdapter()); // TypeID 7
  Hive.registerAdapter(DiaryEntryAdapter()); // TypeID 8
  Hive.registerAdapter(SelectedTrackersAdapter()); // TypeID 11
  Hive.registerAdapter(SelectedGoalsAdapter()); // TypeID 70
  Hive.registerAdapter(GpsActivityEntryAdapter()); // TypeID 60
  Hive.registerAdapter(WeightEntryAdapter()); // TypeID 50
  Hive.registerAdapter(WeightGoalAdapter()); // TypeID 31
  Hive.registerAdapter(ActivityGoalAdapter()); // TypeID 28
  Hive.registerAdapter(DailyGoalProgressAdapter()); // TypeID 33
  Hive.registerAdapter(WeeklyWeightEntryAdapter()); // TypeID 32
  Hive.registerAdapter(MenstrualCycleEntryAdapter()); // TypeID 43
  Hive.registerAdapter(WorkoutActivityAdapter()); // TypeID 41
  Hive.registerAdapter(MeditationGoalAdapter()); // TypeID 98
  Hive.registerAdapter(DailyMeditationProgressAdapter()); // TypeID 97

  await Hive.openBox('settings');
  await Hive.openBox('medicationAlertsSent');
  await Hive.openBox('menstrualCycleBox');
  await Hive.openBox('gps_activities');
  await Hive.openBox('gpsActivity');

  await NotificationService.initialize();
  await LocalisationSettingsService.init();

  // Load saved locale
  last savedLocaleCode = LocalisationSettingsService.getSelectedLocale();
  last initialLocale = savedLocaleCode != null ? Locale(savedLocaleCode) : null;

  runApp(
    MultiProvider(
      suppliers: [
        ChangeNotifierProvider(create: (_) => ThemeNotifier()),
        ChangeNotifierProvider(create: (_) => LocaleNotifier()..setLocale(initialLocale)),
      ],
      youngster: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({tremendous.key});

  @override
  Widget construct(BuildContext context) {
    last themeNotifier = Supplier.of(context);
    last localeNotifier = Supplier.of(context);

    return MaterialApp(
        title: 'Pebbl',
        navigatorKey: navigatorKey,
        theme: AppTheme.lightTheme,
        darkTheme: AppTheme.darkTheme,
        themeMode: themeNotifier.themeMode,
        debugShowCheckedModeBanner: false,
        residence: const NativeSplashWrapper(),
        locale: localeNotifier.locale,
        localizationsDelegates: const [
          AppLocalizations.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
        ],
        supportedLocales: AppLocalizations.supportedLocales,
        localeResolutionCallback: (locale, supportedLocales) {
          for (var supportedLocale in supportedLocales) {
            if (supportedLocale.languageCode == locale?.languageCode &&
                supportedLocale.countryCode == locale?.countryCode) {
              return supportedLocale;
            }
          }
          return const Locale('en', 'GB');
        }
    );
  }
}

2.  Native splash wrapper

import 'package deal:flutter/materials.dart';
import 'package deal:pebbl/screens/login/auth_gate.dart'; // ✅ Now this works

class NativeSplashWrapper extends StatefulWidget {
  const NativeSplashWrapper({tremendous.key});

  @override
  State createState() => _NativeSplashWrapperState();
}

class _NativeSplashWrapperState extends State {
  bool _ready = false;

  @override
  void initState() {
    tremendous.initState();
    _init();
  }

  Future _init() async {
    await Future.delayed(const Period(milliseconds: 100));
    if (mounted) {
      setState(() {
        _ready = true;
      });
    }
  }

  @override
  Widget construct(BuildContext context) {
    if (!_ready) {
      return const Scaffold(
        backgroundColor: Coloration(0xFFF5F5F5),
        physique: Middle(
          youngster: Picture(
            picture: AssetImage('belongings/photographs/pebbl_logo.png'),
            width: 200,
            top: 200,
          ),
        ),
      );
    }
    return const AuthGate();
  }
}
3. Pubspec.yaml (snippet for flutter native splash)

flutter_native_splash:
  colour: "#F5F5F5"
  picture: belongings/photographs/dev_logo.png
  fullscreen: true
  android: true
  ios: true

  android_12:
    picture: belongings/photographs/android12_dev_logo.png
4. Auth gate

import 'package deal:flutter/materials.dart';
import 'package deal:firebase_auth/firebase_auth.dart';
import 'package deal:pebbl/screens/login/splash_screen.dart';
import 'package deal:pebbl/screens/login/login_screen.dart';
import 'package deal:pebbl/widgets/pebbl_app.dart'; // We’ll extract PebblApp too (see beneath)

class AuthGate extends StatelessWidget {
  const AuthGate({tremendous.key});

  @override
  Widget construct(BuildContext context) {
    return StreamBuilder(
      stream: FirebaseAuth.occasion.authStateChanges(),
      builder: (context, authSnapshot) {
        last isLoggedIn = authSnapshot.hasData;
        last display screen = isLoggedIn ? SplashScreen() : const LoginScreen();
        return PebblApp(initialScreen: display screen);
      },
    );
  }
}
5. Pebbl app widget

import 'package deal:flutter/materials.dart';
import 'package deal:pebbl/screens/touchdown/landing_screen.dart';
import 'package deal:pebbl/companies/notification_service.dart';
import 'package deal:pebbl/utils/logger.dart';
import 'package deal:pebbl/important.dart'; // for navigatorKey

class PebblApp extends StatefulWidget {
  last Widget initialScreen;

  const PebblApp({tremendous.key, required this.initialScreen});

  @override
  State createState() => _PebblAppState();
}

class _PebblAppState extends State with WidgetsBindingObserver {
  @override
  void initState() {
    tremendous.initState();
    WidgetsBinding.occasion.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.occasion.removeObserver(this);
    tremendous.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      last payload = NotificationService.getAndClearPendingPayload();
      if (payload != null) {
        Logger.log('App resumed. Routing to payload: $payload');
        navigatorKey.currentState?.pushAndRemoveUntil(
          MaterialPageRoute(builder: (_) => LandingScreen(payload: payload)),
              (route) => false,
        );
      }
    }
  }

  @override
  Widget construct(BuildContext context) {
    return GestureDetector(
      onTap: () => FocusScope.of(context).unfocus(),
      youngster: widget.initialScreen,
    );
  }
}
6. Splash display screen

import 'package deal:flutter/basis.dart';
import 'package deal:pebbl/utils/logger.dart';
import 'dart:io';
import 'package deal:device_info_plus/device_info_plus.dart';
import 'package deal:flutter/materials.dart';
import 'package deal:firebase_auth/firebase_auth.dart';
import 'package deal:package_info_plus/package_info_plus.dart';
import 'package deal:pebbl/screens/touchdown/landing_screen.dart';
import 'package deal:pebbl/screens/login/login_screen.dart';
import 'package deal:permission_handler/permission_handler.dart';
import 'package deal:pebbl/companies/notification_service.dart';
import 'package deal:geolocator/geolocator.dart';

class SplashScreen extends StatefulWidget {
  last String? payloadOverride;

  const SplashScreen({tremendous.key, this.payloadOverride});

  @override
  State createState() => _SplashScreenState();
}

class _SplashScreenState extends State with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;
  String _version = '';

  @override
  void initState() {
    tremendous.initState();
    _controller = AnimationController(
      period: const Period(seconds: 2),
      vsync: this,
    )..ahead();

    _animation = CurvedAnimation(
      mother or father: _controller,
      curve: Curves.easeInOut,
    );

    _init();
  }

  Future _init() async {
    strive {
      last data = await PackageInfo.fromPlatform();
      setState(() {
        _version = 'v${data.model}+${data.buildNumber}';
      });
      if (kDebugMode) {
        Logger.log('✅ Bundle data loaded');
      }
    } catch (e) {
      if (kDebugMode) {
        Logger.log('❌ Bundle data failed: $e');
      }
      _version = 'v1.0.0';
    }

    // 🔒 iOS location permission verify
    strive {
      if (Platform.isIOS) {
        last serviceEnabled = await Geolocator.isLocationServiceEnabled();
        if (kDebugMode) {
          Logger.log('✅ [iOS] Location service enabled: $serviceEnabled');
        }
        if (serviceEnabled) {
          var permission = await Geolocator.checkPermission();
          if (kDebugMode) {
            Logger.log('✅ [iOS] Location permission standing: $permission');
          }
          if (permission == LocationPermission.denied) {
            permission = await Geolocator.requestPermission();
            if (kDebugMode) {
              Logger.log('✅ [iOS] Location permission requested: $permission');
            }
          }
        }
      }
    } catch (e) {
      if (kDebugMode) {
        Logger.log('iOS Location permission request failed: $e');
      }
    }

    // ✅ Android 13+ notification permission
    strive {
      if (Platform.isAndroid) {
        last androidInfo = await DeviceInfoPlugin().androidInfo;
        if (kDebugMode) {
          Logger.log('✅ Android SDK: ${androidInfo.model.sdkInt}');
        }
        if (androidInfo.model.sdkInt >= 33) {
          last standing = await Permission.notification.request();
          if (kDebugMode) {
            Logger.log('✅ Notification permission: $standing');
          }
          if (!standing.isGranted) {
            if (kDebugMode) {
              Logger.log('Notification permission denied');
            }
            // Optionally present a dialog right here
          }
        }
      }
    } catch (e) {
      if (kDebugMode) {
        Logger.log('Notification permission request failed: $e');
      }
    }

    // ✅ Android location permissions: foreground and background
    strive {
      if (Platform.isAndroid) {
        // ✅ 1. Test and request notification permission (Android 13+)
        last notifStatus = await Permission.notification.standing;
        if (!notifStatus.isGranted) {
          if (kDebugMode) {
            Logger.log('🔔 Requesting notification permission...');
          }
          last notifResult = await Permission.notification.request();
          if (kDebugMode) {
            Logger.log('🔔 Notification permission outcome: $notifResult');
          }
        }

        // ✅ 2. Test foreground location permission
        if (kDebugMode) {
          Logger.log('📍 Checking foreground location permission...');
        }
        var fgStatus = await Permission.location.standing;
        if (kDebugMode) {
          Logger.log('📍 Foreground location permission standing: $fgStatus');
        }

        if (!fgStatus.isGranted) {
          if (kDebugMode) {
            Logger.log('📍 Requesting foreground location permission...');
          }
          fgStatus = await Permission.location.request();
          if (kDebugMode) {
            Logger.log('📍 Foreground location permission outcome: $fgStatus');
          }
        }

        // ✅ 3. Test background location permission (if foreground granted)
        if (fgStatus.isGranted) {
          if (kDebugMode) {
            Logger.log('📍 Checking background location permission...');
          }
          var bgStatus = await Permission.locationAlways.standing;
          if (kDebugMode) {
            Logger.log('📍 Background location permission standing: $bgStatus');
          }

          if (!bgStatus.isGranted) {
            if (kDebugMode) {
              Logger.log('📍 Requesting background location permission...');
            }
            bgStatus = await Permission.locationAlways.request();
            if (kDebugMode) {
              Logger.log('📍 Background location permission outcome: $bgStatus');
            }
          } else {
            if (kDebugMode) {
              Logger.log('✅ Background location permission already granted');
            }
          }
        } else {
          if (kDebugMode) {
            Logger.log('❌ Foreground location denied, skipping background request');
          }
        }
      }
    } catch (e) {
      if (kDebugMode) {
        Logger.log('❗ Permission request failed: $e');
      }
    }


    await Future.delayed(const Period(seconds: 2));
    if (!mounted) return;

    last consumer = FirebaseAuth.occasion.currentUser;
    if (kDebugMode) {
      Logger.log('SplashScreen: currentUser = ${consumer?.uid}');
    }
    last payload = widget.payloadOverride ??
        NotificationService.getInitialPayload() ??
        NotificationService.consumePendingPayload();
    if (kDebugMode) {
      Logger.log('SplashScreen init: Firebase consumer: ${consumer?.uid}, payload: $payload');
    }
    if (kDebugMode) {
      Logger.log('SplashScreen: payload resolved = $payload');
    }

    if (consumer != null) {
      strive {
        if (kDebugMode) {
          Logger.log('Calling rescheduleAllReminders...');
        }
        await NotificationService.rescheduleAllReminders()
            .timeout(const Period(seconds: 5));
        if (kDebugMode) {
          Logger.log('rescheduleAllReminders accomplished');
        }
      } catch (e) {
        if (kDebugMode) {
          Logger.log('rescheduleAllReminders failed or timed out: $e');
        }
      }
    }

    if (!mounted) return;

    Navigator.of(context).pushReplacement(
      MaterialPageRoute(
        builder: (_) => consumer == null
            ? const LoginScreen()
            : LandingScreen(payload: payload),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    tremendous.dispose();
  }

  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      backgroundColor: const Coloration(0xFFF5F5F5),
      physique: Column(
        mainAxisAlignment: MainAxisAlignment.heart,
        youngsters: [
          const Spacer(),
          FadeTransition(
            opacity: _animation,
            child: Center(
              child: Image.asset(
                'assets/images/pebbl_logo.png',
                width: 200,
                height: 200,
              ),
            ),
          ),
          const Spacer(),
          Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: Text(
              _version,
              style: const TextStyle(color: Colors.black54),
            ),
          ),
        ],
      ),
    );
  }
}
AppDelegate

import UIKit
import Flutter
import UserNotifications
import AVFAudio
import GoogleMaps // 👈 Add this import for Maps

@important
@objc class AppDelegate: FlutterAppDelegate {
  //lazy var flutterEngine = FlutterEngine(identify: "my_engine")
  override func software(
    _ software: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    UIApplication.shared.ignoreSnapshotOnNextApplicationLaunch()

// Begin engine (plugins auto-register when the engine is hooked up to the view)
    //flutterEngine.run()
    // Arrange audio playback class
    do {
      strive AVAudioSession.sharedInstance().setCategory(
        .playback,
        mode: .default,
        choices: [.mixWithOthers]
      )
      strive AVAudioSession.sharedInstance().setActive(true)
    } catch {
      print("Didn't set audio session class.")
    }

    // ✅ Register Google Maps API key
    GMSServices.provideAPIKey("key") // 👈 Change along with your precise key

    // Guarantee notification faucets are delivered to Flutter
    UNUserNotificationCenter.present().delegate = self

    return tremendous.software(software, didFinishLaunchingWithOptions: launchOptions)

  func applicationWillResignActive(_ software: UIApplication) {
      // Add a white view over the window earlier than backgrounding
      let whiteView = UIView(body: window?.bounds ?? .zero)
      whiteView.backgroundColor = UIColor.white
      whiteView.tag = 999 // So we are able to take away it later
      window?.addSubview(whiteView)
  }

  func applicationDidBecomeActive(_ software: UIApplication) {
      // Take away the white view when app turns into energetic
      if let whiteView = window?.viewWithTag(999) {
          whiteView.removeFromSuperview()
      }
  }
  }
}
SceneDelegate

import UIKit
import Flutter

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?

  func scene(_ scene: UIScene,
             willConnectTo session: UISceneSession,
             choices connectionOptions: UIScene.ConnectionOptions) {

    guard let windowScene = (scene as? UIWindowScene) else { return }

    let window = UIWindow(windowScene: windowScene)

    //let appDelegate = UIApplication.shared.delegate as! AppDelegate
    //let flutterEngine = appDelegate.flutterEngine

    let flutterViewController = FlutterViewController()

    GeneratedPluginRegistrant.register(with: flutterViewController.engine)

    window.rootViewController = flutterViewController
    self.window = window
    window.makeKeyAndVisible()
  }
}