# @doorstepai/dropoff-sdk 中文文档

规范地址：https://npmcn.com/package/%40doorstepai/dropoff-sdk/

版本：2\.2\.10
npm 元数据更新时间：2026-11-06T06:14:17.314Z
中文译文更新时间：2026-11-12T16:39:25.588Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40doorstepai/dropoff-sdk
原文对照：https://npmcn.com/package/%40doorstepai/dropoff-sdk/?lang=original
项目主页：https://github.com/doorstep-ai/DoorstepAIDropoffReactNativeSDK#readme
源码仓库：https://github.com/doorstep-ai/DoorstepAIDropoffReactNativeSDK

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：44.2 MB，77 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.11\.0
- 运行依赖：1 个
- peer 依赖：react \*，react-native \*
- 首次发布：2025-04-17T12:07:34.744Z
- 最新版本发布：2026-11-06T06:14:17.127Z
- 近 30 天下载量：2473（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：56（近 12 个月 23 个）

## 中文简介

门阶.ai dropoff sdk for React Industrial (英语)

## 安装

```sh
npm install @doorstepai/dropoff-sdk
```

也可以使用：`pnpm add @doorstepai/dropoff-sdk`、`yarn add @doorstepai/dropoff-sdk`、`bun add @doorstepai/dropoff-sdk`

## README

# DoorstepAI Dropoff SDK 原生反应

这个 `@doorstepai/dropoff-sdk` 提供一套工具,将发送跟踪整合到您的 React Natural 应用程序中。 这个SDK可以使您的传送接口与DoorstepAI的后端系统无缝协调.

## \* 安装

```bash
npm install @doorstepai/dropoff-sdk
```

* * *

## 开始

### 1\. 联合国. **导入组件**

```tsx
import {
  RootDoorstepAI,
  DoorstepAI
} from '@doorstepai/dropoff-sdk';
```

### 2\. 联合国. **添加 `RootDoorstepAI` 转到根文件**

将以下组件放入您的根 `App.tsx` 或主条目文件 :

```jsx
import { RootDoorstepAI } from "@doorstepai/dropoff-sdk"

const App = () => {
  return (
    <View>
        <RootDoorstepAI 
          apiKey="YOUR_API_KEY_HERE" 
          notificationTitle="Some Notification Title"
          notificationText="Some Notification Text"
        />
        {/** Your App Components */}
  )
}
```

此选项设置 API 密钥, 初始化 SDK, 并在 应用启动。 里面的每一部分都有一个点心 `DoorstepAI` - 那个 组件存在所以只想要默认流量的主机不需要写入 这个.

通知的标题/文本 传递给Android的前台服务,所以你得到 完全控制文本.

可选道具 :

| 道具 | 默认 | 它会做什么 |
| --- | --- | --- |
| `permissions` | _(每个桶)_ | 白名单交给 `requestPermissions`数字 : **这些水桶是需要的,别无他法.** 见 [权限](https://npmcn.com/package/%40doorstepai/dropoff-sdk/#readme--permissions)。 。 。 . |
| `requestBackgroundLocation` | `true` | 运行第二阶段 `locationAlways` 一旦前方位置获准,则请求。 它必须是第二阶段,因为Android自动拒绝一个背景请求与前台的连接。 如果你自己上船 要求"永远好"的话就关掉. |
| `requestBluetooth` | `true` | **折旧** ——使用 `permissions`它可以缩小任何一桶 而不是这个. `false` 从默认的白名单中去掉平台的"蓝牙"桶. |

```jsx
<RootDoorstepAI
  apiKey="YOUR_API_KEY_HERE"
  permissions={['location', 'motion']}   // no Bluetooth, no notifications
/>
```

* * *

## 示例使用法

使用SDK的功能来跟踪和更新交付事件. 下面是使用按钮的常见例子.

```jsx
import { Button } from 'react-native';
import { DoorstepAI } from "@doorstepai/dropoff-sdk"

// Start a delivery using a Google Place ID
<Button title="Start Delivery" onPress={() => {
  DoorstepAI.startDeliveryByPlaceID('destination_place_id', 'delivery_id_1');
}} />

// Start a delivery using an address
<Button title="Start Delivery by Address" onPress={() => {
  const address = {
    streetNumber: '123',
    route: 'Main St',
    subPremise: 'Apt 4B',
    locality: 'New York',
    administrativeAreaLevel1: 'NY',
    postalCode: '10001'
  };
  DoorstepAI.startDeliveryByAddress(address, 'delivery_id_1');
}} />

// Send "taking_pod" event
<Button title="Taking POD" onPress={() => {
  DoorstepAI.newEvent('taking_pod', 'delivery_id_1');
}} />

// Send "pod_captured" event
<Button title="POD Captured" onPress={() => {
  DoorstepAI.newEvent('pod_captured', 'delivery_id_1');
}} />

// End the delivery
<Button title="End Delivery" onPress={() => {
  DoorstepAI.stopDelivery('delivery_id_1');
}} />
```

* * *

## SDK API软件

下方的每一种方法都是对原生iOS/Android SDK的薄接通. 在一个 只有一个平台存在方法 它这么说,它 **拒绝** 另一方面 而不是解决一个捏造的价值——一个悄悄解决的帮助者 `true`编号 :`[]` 将读作"被授予"/"不需要"到跨平台主机.

### 设置

| 方法 | 说明 |
| --- | --- |
| `init(notificationTitle?, notificationText?): Promise<void>` | 仅限Android(在iOS上没有-op). 交给你 `<RootDoorstepAI />`。标题/文本出现在前景服务通知上. |
| `setApiKey(apiKey): void` | 收集 API 密钥 . |
| `setDoorstepGoApiKey(apiKey): void` | 门步 去吧,这是个 **独立证书和域**; 不使用时不使用. |
| `configureRemoteLogging({ enabled, minLevel?, flushIntervalSeconds?, batchSize?, maxQueueSize? }): void` | iOS只(在Android上没有操作,它驱动远程配置的远程日志). |
| `debugStateJson(): Promise<string>` | 仅iOS. 用于错误报告的自由格式内态垃圾堆——从不在其上分出. |
| `retryGnssCallbacks(): Promise<boolean>` | 仅限Android. 在OS静悄悄地停止发送后重新注册生GNSS召回. |
| `enableDevMode(apiKey)` 编号 : `validateDevModeAccess()` 编号 : `disableDevMode()` | 开发工具。 后面两个是Android 唯一的答案 `false` (原始内容存档于2018-03-31). On iOS. |

### 嵌入式门阶 地图

设置单独的门阶 在挂起视图前按键, 然后使用其中任一 名称导出或 `DoorstepAI.EmbedView`数字 :

```tsx
import { DoorstepAI, DoorstepEmbedView } from '@doorstepai/dropoff-sdk';

DoorstepAI.setDoorstepGoApiKey('YOUR_DOORSTEP_GO_API_KEY');

<DoorstepEmbedView
  address="1600 Pennsylvania Avenue NW, Washington, DC"
  deliveryID="delivery-123"
  inlineHeight={300}
  expandedHeight={600}
  borderRadius={16}
  linkAPI="https://api.core.doorstep.ai"
  baseMap="light"
  parkingText="95% of drivers parked here"
  markerColor="#027FB8"
  polygonColor="#3291BC"
  parkingColor="#FF847B"
  onModeChanged={(mode) => console.log('embed mode', mode)}
  onLoad={() => console.log('embed navigation started')}
  onSuccess={() => console.log('embed ready')}
  onError={(message, error) => console.warn(error.code, error.stage, message)}
/>
```

`DoorstepAI.EmbedView` 接受同样的道具. `mode` 是可选的: 省略它以让 本地扩展/缩放控制拥有该模式,或提供该模式作为控制 道具 (英语). 组件默认其高度到活动模式的高度 `inlineHeight` 或者说 `expandedHeight`; 明示 `style.height` 推翻了这种行为. `borderRadius` (点/dp,默认为0)弹出本土地图卡本身——使用它 改为 `style.borderRadius`,不剪辑本地地图。 留着 可见时挂载视图, 因为正在解析 Android 的 WebGL 后置地图 销毁其图形上下文.

用于预装和显示相同的挂载地图 `onSuccess`,参见 [`embed-preload.example.tsx`](https://npmcn.com/package/%40doorstepai/dropoff-sdk/embed-preload.example.tsx)它让本地人 视图在装入时以不透明零的全尺寸附加,禁用触摸并 隐藏时可访问性,并处理出错和有限制的预装出错. 使用 `show={false}` ,然后设定为 `true` 一次公开 准备 保持其母机上架并避免导航去除本地屏幕. 这在内存中保留了活视图;它不会下载可耐用的离线地图.

`onLoad` 在创建签名链接后开始导航时起火; `onLoading` 仍然是兼容的别名. `onSuccess` 页面报告时起火 地图准备,所以用它来揭示一个预装地图. `onLoad` 一个人不意味着 地图准备好了 这些回调需要更新的 JavaScript 软件包和 a 在 Android 和 iOS 上重建本地应用程序; 单独更新 OTA JavaScript 无法添加缺失的本地回调 .

可选 `mapStyleToggle`, (中文(简体) ), `gpsRecenterToggle`, (中文(简体) ), `streetViewToggle`,以及 `expandContractToggle` 道具默认为 `true` 在两个平台上. `endpoint={{lat, lng}}` 转发目的地坐标, `fitGpsOnStart` 默认为 `false`,以及 `readyTimeoutSeconds` 默认为 `15`。本地按钮分析直接通过 本地SDK的WebView桥通向Doorstep Go; React Industrial 不需要转发它们.

`onError(message, error)` 将遗言作为第一个论据 `DoorstepEmbedError` 作为第二个: `code`, (中文(简体) ), `stage`, (中文(简体) ), `message`, (中文(简体) ), `isRetryable`选择 `httpStatusCode`编号 :`requestId`。两个平台使用相同的字段名称和enum值. `onLoading` 报告导航开始; `onSuccess` 报告页面准备情况.

### 交货

所有四个开始者都采用同样的跟踪 `StartDeliveryOptions`数字 :

```ts
type StartDeliveryOptions = {
  timeoutSeconds?: number;              // hard session cap; OMIT for none
  manualForeground?: boolean;           // Android only: host owns the FGS
  customerId?: string;
  driverId?: string;
};
```

| 方法 | 说明 |
| --- | --- |
| `startDeliveryByAddressString(address, deliveryId, timeoutSeconds?, coordinates?, options?)` | 偏爱. 过 `coordinates` 当你有他们. |
| `startDeliveryByAddress(address: AddressType, deliveryId, timeoutSeconds?, coordinates?, options?)` | 结构化地址. |
| `startDeliveryByPlaceID(placeID, deliveryId, timeoutSeconds?, options?)` | Google Place ID (英语). |
| `startDeliveryByLatLng(lat, lng, subUnit, deliveryId, timeoutSeconds?, options?)` | **折旧** ——使用地址方法 `coordinates`。 。 。 . |
| `startDeliveryByPlusCode(plusCode, deliveryId, timeoutSeconds?, options?)` | **折旧** 一样. |
| `markDropoff(deliveryId, 'pod' | 'non_pod'): Promise<void>` | 记录完成并关闭路线-地理 EXIT站. |
| `stopDelivery(deliveryId): Promise<void>` |  |
| `newEvent(eventName, deliveryId, timestamp?): Promise<...>` | `timestamp` 是一个可选的时代 **秒数**。 。 。 . |

```ts
type AddressType = {
  streetNumber: string;
  route: string;
  subPremise: string;                 // apartment, suite, unit
  locality: string;                   // city
  administrativeAreaLevel1: string;   // state/province
  postalCode: string;
};
```

**`timeoutSeconds` 省略意味着没有备份**,这是本地行为 两个平台。 (这个包装器的更古老的版本 替换了3600 s在这里和 一小时后就停止运送

一个跨平台的区别 包装纸没有纸: **Android 解决 服务器会话 id** (单位:千美元)`{"id":"<uuid>"}`)从起步和 **iOS 解决 无** ——土著回返 `Void` 在这里。 将坚定的承诺视为成功 信号,而不是真实的返回值。 在iOS上,听SDK的 `sessionServerIdAssignedNotification` 本地的,如果你需要身份证.

### 路线地缘

SDK栅栏每站并自动启动合格ENTER的快递. 服务器拥有 半径和EXIT政策`misc.geofence.waitForDropoff`: 需要真实/缺失 `markDropoff` 在ExIT停止会话之前; 假允许未加标记的ExIT并保持停站武装. 全程遥测也是服务器控制的. 背景路线需要位置 授权和本地 SDK 支持的前景/背景执行设置; 授权总是提供最广泛的恢复支持.

```ts
type DeliveryStop = {
  deliveryId: string;
  address: string;
  latitude: number;
  longitude: number;
  routeStopId?: string;    // stable identity; defaults to deliveryId
  radiusMeters?: number;   // deprecated, ignored; radius is server controlled
  customerId?: string;
  driverId?: string;
};

type RouteOptions = {
  defaultRadiusMeters?: number;          // deprecated, ignored
  timeoutSeconds?: number;               // per auto-started session
  autoStopAfterDropoffSeconds?: number;
  manualForeground?: boolean;            // Android only; ignored on iOS
  maxAgeSeconds?: number;                 // Android only
  clientRouteId?: string;
  driverId?: string;
  metadata?: Record<string, string>;
};
// RouteGeofenceOptions remains a deprecated alias for source compatibility.
```

对于Android线路,使用主机拥有的定位前景服务,开始 当应用程序可见时服务, 然后等待准备, 然后再开始路径 :

```ts
await Location.startLocationUpdatesAsync(LOCATION_TASK, locationOptions);
await DoorstepAI.waitForHostForegroundService({
  timeoutMs: 10_000,
  serviceClassName: 'expo.modules.location.services.LocationTaskService',
});
await DoorstepAI.startRouteGeofencing(stops, { manualForeground: true });
```

`waitForHostForegroundService(options?): Promise<void>` 仅限Android和 拒绝iOS。 它立即检查,然后每100米 使用Android的自用 运行服务查询. `timeoutMs` 默认为 10000 并接受整数 0至120 000;0立即检查一次。 奥米 `serviceClassName` 改为 除了Doorstep的跟踪服务之外,接受应用程序中的任何前景服务. 对博览会来说,与其服务等级相匹配,因此无关的服务不能满足 等会 拒绝有本地密码 `HOST_FGS_TIMEOUT`, (中文(简体) ), `HOST_FGS_CHECK_FAILED`,或 `HOST_FGS_CANCELLED` (模块撕裂). 查询被贬值,但仍支持检查呼叫者自己的服务.

成功是前景状态的快照 不是地点服务类型的证明, 权限、新修正或未来更新时间。 保持主机位置服务的生命力 整个路线。 这种方法不会启动服务,初始化跟踪, 或更改 `manualForeground`。仅更新JavaScript是不够的:重建 更新了 SDK 之后的本地Android app .

| 方法 | 说明 |
| --- | --- |
| `startRouteGeofencing(stops, options?): Promise<void>` | 如果没有停站,则拒绝 `deliveryId` +坐标. |
| `updateRouteStops(stops): Promise<void>` | 替换已存在的列表. **删除有活动会话的站点立即停止** (理由 `removed_from_route`) ——不是EXIT驱动,不是滴滴式. 不延长路线租约. |
| `stopRouteGeofencing(): Promise<void>` | 拆解被交给追踪服务/区域管理员,所以 `getMonitoredStops()` 还可以暂时显示旧名单. |
| `resumeRouteGeofencingIfNeeded(): Promise<void>` | **每次发射都叫这个.** 每个发射主机的义务:没有它,Android会默默地失去穿越一个过程的路由监测. |
| `getMonitoredStops(): Promise<DeliveryStop[]>` | SDK的车 _意图_ 注册,而不是操作系统注册区域集. |
| `isRouteGeofencingActive(): Promise<boolean>` | 持久路线意图,独立于主动交付. |
| `getActiveRouteId(): Promise<string | null>` | 两站台均设有Canonical SDK路由UUID. |
| `getActiveRouteRevision(): Promise<number | null>` | 目前明显修改,或无路线无效. |
| `addMetadata(deliveryId, metadata): Promise<void>` | 发送会话开始之前或之后附加 JSON 元数据 . |
| `addGeofenceSessionListener(cb): EmitterSubscription | undefined` | `{ deliveryId, type: 'STARTED' | 'STOPPED', reason }`调用 `.remove()` 以取消订阅. |

```ts
const sub = DoorstepAI.addGeofenceSessionListener(({ deliveryId, type, reason }) => {
  console.log(type, deliveryId, reason);
});
await DoorstepAI.startRouteGeofencing(stops, { clientRouteId: 'route-123', driverId: 'driver-123' });
// ...later
sub?.remove();
```

### 权限

`checkPermissions`, (中文(简体) ), `checkPermissionsJson`, (中文(简体) ), `requestPermissions`, (中文(简体) ), `allPermissionBuckets`, (中文(简体) ), `notePermissionRequestResult`,并仅使用Android查询 帮手 见 [权限](https://npmcn.com/package/%40doorstepai/dropoff-sdk/#readme--permissions) ——本节为参考.

* * *

## 最佳做法

-   总是包 `DoorstepAI` API打电话来 `try/catch` 或用途 `.catch()` 在适用的情况下,可以更好地处理出错.
-   使用 `RootDoorstepAI` 仅包含 **一次** 地点 **根号** 你的应用.
-   确保您的 API 密钥安全存储, 并且不会在生产中被硬码 .
-   总是提供独一无二的 `deliveryId` 每次交付会.
-   跟踪 `deliveryId` 整个送货寿命周期,因为所有操作都需要.

* * *

## 调试

如果事情没有预期的好

-   检查控制台日志 `DoorstepAI initialized` 或错误消息.
-   验证 API 密钥是否有效并被 SDK 接受 .
-   确保设备上正确设置您的权限( 如位置) .
-   证明你用对了 `deliveryId` 每个操作.

* * *

## QQ 权限

用来使用 `@doorstepai/dropoff-sdk` 您必须有效地在您的移动应用程序的配置文件中包含相应的权限 .

### iOS系统

在你身边 `Info.plist`,包括下列使用说明:

```xml
<!-- Location Usage Descriptions -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires access to your location for delivery tracking.</string>
<key>NSLocationAlwaysAndWhenInUseUsage</key>
<string>This app requires access to your location to provide continuous tracking even in the background.</string>

<!-- Optional: Motion & Sensor Data (if applicable) -->
<key>NSMotionUsageDescription</key>
<string>This app uses motion data to enhance delivery tracking accuracy.</string>

<!-- Required if you let Bluetooth default to on (see the permission API below).
     Without this key the SDK skips the Bluetooth request with a warning. -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to improve delivery location accuracy.</string>

<!-- Background Location Mode -->
<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>
```

### 安卓尔

SDK自己的名单 已经宣布了它需要的每一个许可 把它们放到你的应用软件上 只有在您想要在 你们自己 `AndroidManifest.xml`数字 :

```xml
<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" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-feature android:name="android.hardware.sensor.accelerometer" />
<uses-feature android:name="android.hardware.sensor.gyroscope" />
<uses-feature android:name="android.hardware.sensor.barometer" />
<uses-feature android:name="android.hardware.sensor.compass" />
<uses-feature android:name="android.hardware.sensor.proximity" />
```

### 运行时请求

`<RootDoorstepAI />` 这样做是为了你。 驱动时直接使用 API 从您本人的入职权限流出——每一种方法代表给本地人 SDK自己的白名单许可 API,所以桶,州,即时命令 "我会拒绝问什么,为什么" 计划留下来 无论SDK说什么 他们是.

**一个请求者,两个平台。 没有任何论据要求一切 白名单和它之外的一切 从来没有要求.** 不要在树枝上 `Platform.OS` 请求权限——分支在包装箱内,在 `DoorstepAI.requestPermissions(_ permissions:…)` (iOS)和 `DoorstepAI.requestPermissions(activity, permissions)` (Android) (英语).

```ts
await DoorstepAI.requestPermissions();                       // every bucket
await DoorstepAI.requestPermissions(['locationWhenInUse']);   // only this one
await DoorstepAI.requestPermissions({                         // object form
  permissions: ['location', 'motion'],
  onlyIfNotDetermined: true,   // iOS
  timeoutSeconds: 60,
});
```

#### 弹夹

A 类 **桶头** 是一个用户可见的操作系统决定。 它们是故意针对OS的, 由于平台是,只有两个位置桶存在于两个平台上:

| 桶头 | iOS系统 | 机器人 |
| --- | --- | --- |
| `locationWhenInUse` | `requestWhenInUseAuthorization` | `ACCESS_FINE_LOCATION` + 键 `ACCESS_COARSE_LOCATION` |
| `locationAlways` | `requestAlwaysAuthorization` | `ACCESS_BACKGROUND_LOCATION` |
| `motionFitness` | 运动和适合性 | —— 说 |
| `activityRecognition` | —— 说 | `ACTIVITY_RECOGNITION` |
| `bluetooth` | `CBCentralManager` | —— 说 |
| `bluetoothScan` | —— 说 | `BLUETOOTH_SCAN` (API 31+) (英语) |
| `nearbyWifiDevices` | —— 说 | `NEARBY_WIFI_DEVICES` (API 33+) (英语) |
| `notifications` | —— 说 | `POST_NOTIFICATIONS` (API 33+) (英语) |

你可以通过 **两个平台的** 任一平台上的名称: 收发器翻译 对应方(`motionFitness` ⇄ `activityRecognition`, (中文(简体) ), `bluetooth` ⇄ `bluetoothScan`)),所以一个白名单对两者都有效,没有 `Platform.OS` 树枝。 A 类 完全没有对应名称( e)`notifications` 在iOS上)回来 `unsupported` 而不是沉寂下来 粗口别名 `'location'` (-两个位置桶), `'motion'` 编号 : `'activity'` 财务报告和审定财务报表 `'bluetooth'` 还在 这些是出版的 2.x API 拍摄.

`DoorstepAI.allPermissionBuckets()` 返回此平台的列表 在不硬编码的情况下建立权限屏幕.

#### 国家

八个州, **两个平台上相同的名称**,所以主机代码分支一次:

| 状态 | 含义 |
| --- | --- |
| `granted` | 就现在 |
| `notDetermined` | 从未询问; 请求将显示对话框 |
| `whenInUseOnly` | **前方位置,背景没有.** 只有报告过 `locationAlways` |
| `denied` | 拒绝, 仍然可能出现另一个提示( 只有Android) |
| `permanentlyDenied` | 拒绝 , 无法进一步迅速 —— 深链接到设置 。 每一个iOS拒绝到这里 |
| `restricted` | 被设备策略 / MDM / 屏幕时间所屏蔽 |
| `unavailable` | 操作系统或硬件没有。 不是失败 |
| `notDeclared` | **您的建筑缺少声明** (单位:千美元)`<uses-permission>` 编号 : `NS…UsageDescription`) (中文(简体) ). 不是用户拒绝——可以由您修复 |

`whenInUseOnly` 确是负载的 **从来没有把它当作 `granted`。 。 。 .** 背景情况 收集和路由的地平线不起作用.

```ts
// Read the current state. Pure observation — never shows a dialog.
const { statuses } = await DoorstepAI.checkPermissions();
if (statuses.locationAlways?.state === 'whenInUseOnly') {
  // foreground-only: no background collection, no route geofencing
}
if (statuses.locationWhenInUse?.state === 'permanentlyDenied') {
  // a request would be answered instantly with no dialog — send them to Settings
}
```

#### 请求的答案是什么呢

`requestPermissions` **只在用户回答后解决**,与解决 状态——在提示时读取状态将是一个谎言。 土生土长 而不是默默不作的:

```ts
const result = await DoorstepAI.requestPermissions();
result.requested;          // buckets a dialog was actually raised for
result.alreadyDetermined;  // already answered, so left alone
result.unavailable;        // absent on this device / missing from this build
result.deferred;           // deliberately skipped, with the reason
result.statuses;           // state of every whitelisted bucket, after settling
result.permissions;        // legacy { location, motion, bluetooth } view
result.unsupported;        // whitelist entries this platform has no bucket for
```

**期待 `locationAlways` 内 `deferred` 在全白名单呼叫.** 只有这样 请求 _一个人_ 仅限 _之后_ 前地位置获准——Android自动识别 捆绑的背景询问,iOS 显示 When-In-User 提示并给出 总是在以后按自己的时间表升级. 因此标准双相流是:

```ts
const first = await DoorstepAI.requestPermissions();
if (first.statuses.locationWhenInUse?.state === 'granted') {
  await DoorstepAI.requestPermissions(['locationAlways']);
}
```

设备测量, Moto G stylus 5G / Android 14: 一个全白名单的调取 在一个批次中返回5个可询问对话框 `deferred: { locationAlways: 'ACCESS_BACKGROUND_LOCATION cannot be requested before foreground location is granted…' }`. iPhone 16 Pro / iOS 26.6:它提高了 `locationAlways`, (中文(简体) ), `motionFitness` 财务报告和审定财务报表 `bluetooth` 一次一个返回 `deferred: { locationWhenInUse: 'covered by the locationAlways prompt in this call…' }`。 。 。 .

在飞行中打出第二通电话时 无法及时中断 序列: iOS 报告每个桶为 `deferred`,Android 拒绝使用 `E_PERMISSION_REQUEST_IN_FLIGHT`。如果用户从未回答,则等待会在 `timeoutSeconds` (违约120 s),并按现状与州解决.

iOS 来自 SDK 的引导 : **一次,来自用户启动的流程**,而不是从 应用发布.

#### Android: 转发您的捐赠结果( 可选, 值得做)

机器人报告 _不变_ 表示“永久拒绝”和“从未要求” (单位:千美元) **已取消** 对话留下与否认相同的痕迹 。 SDK拒绝猜测, 所以,没有真正的答案 拒绝报告为可重提 `denied`。前进 结果你得到 `permanentlyDenied` ——联署材料承诺解决 而不是在窗口聚焦的热度上:

```kotlin
// MainActivity.kt
import com.doorstepai.dropoffsdk.DoorstepAIModule

override fun onRequestPermissionsResult(
  requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults)
  DoorstepAIModule.notePermissionRequestResult(this, permissions, grantResults)
}
```

也有一个联署材料的切入点(`DoorstepAI.notePermissionRequestResult(permissions, grantResults)`)如果数值到达那里.

#### 遗产三值视图

`statuses` 才是真正的答案 但每个结果都包含 `{ location, motion, bluetooth }` × `granted | denied | prompt` 映射已发布 2.x API 返回,所以现有的主机继续工作. 它从 `statuses`数字 : `whenInUseOnly` 财务报告和审定财务报表 `unavailable` → `granted`, (中文(简体) ), `notDetermined` → `prompt`, (中文(简体) ), 其他一切(包括 `notDeclared`页:1 `denied`。 。 。 .

它不能告诉你的两件事, 这就是为什么它被堕落: While-In-use vs 总是,而主机构建错误与用户拒绝.

`motion` 无条件停留 `granted` 和2.x一样 这是 诚实地回答关键所在——Android的IMU流(acel, Dyro, mag, 需要旋转向量,气压计) **没有** 跑步时间补助,所以运动费是 永远有可能. `activityRecognition` 只增加相继流出的地方, 且 SDK 绝不屏蔽会议; 读取 `statuses.activityRecognition` 页:1 它的真实状态。 在 iOS 时 `motion` 跟踪运动和适切性, 这才是真正的门 `CMMotionActivityManager`, (中文(简体) ), `CMSensorRecorder` 绝对高度.

#### 仅使用 Android 的查询助手

这些拒绝在iOS上而不是解决 `true`编号 :`[]`,是一个跨平台主机 将读作“给予”/“不需要”.

```ts
await DoorstepAI.hasRequiredPermissions();          // -> boolean
await DoorstepAI.hasBackgroundLocationPermission(); // -> boolean
await DoorstepAI.requestBackgroundLocationPermission();

// Want the grant results in JS? Request the SDK's own flat list with RN's API.
const required = await DoorstepAI.getRequiredPermissions();
await PermissionsAndroid.requestMultiple(required);
```

`requestPermissions(['locationAlways'])` 是表达 意图与 `requestBackgroundLocationPermission()`,它报告为什么 操作员会拒绝显示提示.

* * *

## 常见问题

### @doorstepai/dropoff-sdk 是什么？

门阶\.ai dropoff sdk for React Industrial \(英语\)

### 如何安装 @doorstepai/dropoff-sdk？

在项目目录运行 npm install @doorstepai/dropoff-sdk，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（\*）、react-native（\*）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @doorstepai/dropoff-sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @doorstepai/dropoff-sdk 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @doorstepai/dropoff-sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.11\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @doorstepai/dropoff-sdk 可以商用吗？

@doorstepai/dropoff-sdk 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @doorstepai/dropoff-sdk 的下载量有多少？

根据 npm 官方下载统计，@doorstepai/dropoff-sdk 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,473 次，日均约 82 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @doorstepai/dropoff-sdk 还在维护吗？

最新版本 2\.2\.10 发布于 2026/11/06（7 天前）；至今共发布 56 个版本，其中过去 12 个月发布了 23 个；首次发布于 2025/04/17。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

