콘텐츠로 건너뛰기

공유 타겟 시작하기

이 가이드는 앱이 다른 애플리케이션에서 공유 콘텐츠를 수신할 수 있도록 Capacitor 공유 대상 플러그인을 통합하는 과정을 안내합니다.

npm을 사용하여 플러그인을 설치합니다.

Terminal window
npm install @capgo/capacitor-share-target
npx cap sync

<activity> 태그 내부의 AndroidManifest.xml에 인텐트 필터를 추가합니다.

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>

iOS의 경우 공유 확장을 생성해야 합니다.

1. Xcode에서 공유 확장을 생성합니다.

Section titled “1. Xcode에서 공유 확장을 생성합니다.”
  1. Xcode에서 프로젝트를 엽니다.
  2. 파일 > 새로 만들기 > 대상으로 이동합니다.
  3. 확장 프로그램 공유를 선택하고 다음을 클릭합니다.
  4. 이름을 지정하고(예: “ShareExtension”) 마침을 클릭합니다.
  5. 메시지가 표시되면 구성표를 활성화합니다.
  1. 기본 앱 타겟에서 서명 및 기능으로 이동합니다.
  2. + 기능을 클릭하고 앱 그룹을 추가합니다.
  3. 앱 그룹(예: group.com.yourcompany.yourapp)을 생성하거나 선택합니다.
  4. 공유 확장 대상에 대해 반복합니다.

공유 확장은 기본 앱이 액세스할 수 있도록 공유 데이터를 앱 그룹 컨테이너에 저장해야 합니다.

자세한 iOS 설정은 Apple의 공유 확장 문서를 참조하세요.

import { CapacitorShareTarget } from '@capgo/capacitor-share-target';
CapacitorShareTarget.addListener('shareReceived', (event) => {
console.log('Received share event');
console.log('Title:', event.title);
console.log('Texts:', event.texts);
// Handle shared files
if (event.files && event.files.length > 0) {
event.files.forEach(file => {
console.log(`File: ${file.name}`);
console.log(`Type: ${file.mimeType}`);
console.log(`URI: ${file.uri}`);
});
}
});

다음은 다양한 유형의 공유 콘텐츠를 처리하는 포괄적인 예입니다.

import { CapacitorShareTarget } from '@capgo/capacitor-share-target';
class ShareTargetService {
private listener: any;
initialize() {
this.listener = CapacitorShareTarget.addListener('shareReceived', (event) => {
this.handleSharedContent(event);
});
console.log('Share target listener initialized');
}
handleSharedContent(event: any) {
console.log('=== Share Received ===');
// Handle title
if (event.title) {
console.log('Title:', event.title);
this.showNotification('Shared: ' + event.title);
}
// Handle text content
if (event.texts && event.texts.length > 0) {
event.texts.forEach((text: string, index: number) => {
console.log(`Text ${index + 1}:`, text);
this.processSharedText(text);
});
}
// Handle files
if (event.files && event.files.length > 0) {
console.log(`Received ${event.files.length} file(s)`);
event.files.forEach((file: any) => {
console.log('File details:');
console.log(' Name:', file.name);
console.log(' Type:', file.mimeType);
console.log(' URI:', file.uri);
this.processSharedFile(file);
});
}
}
processSharedText(text: string) {
// Check if it's a URL
if (this.isURL(text)) {
console.log('Shared URL detected:', text);
// Handle URL (e.g., create bookmark)
this.saveBookmark(text);
} else {
console.log('Shared text detected');
// Handle plain text (e.g., create note)
this.createNote(text);
}
}
processSharedFile(file: any) {
const fileType = file.mimeType.split('/')[0];
switch (fileType) {
case 'image':
console.log('Processing shared image');
this.handleImage(file);
break;
case 'video':
console.log('Processing shared video');
this.handleVideo(file);
break;
case 'audio':
console.log('Processing shared audio');
this.handleAudio(file);
break;
case 'application':
console.log('Processing shared document');
this.handleDocument(file);
break;
default:
console.log('Processing generic file');
this.handleGenericFile(file);
}
}
handleImage(file: any) {
// Process image file
console.log('Saving image:', file.name);
// Implementation: Save to gallery, upload, etc.
}
handleVideo(file: any) {
// Process video file
console.log('Saving video:', file.name);
}
handleAudio(file: any) {
// Process audio file
console.log('Saving audio:', file.name);
}
handleDocument(file: any) {
// Process document file
console.log('Saving document:', file.name);
}
handleGenericFile(file: any) {
// Process generic file
console.log('Saving file:', file.name);
}
isURL(text: string): boolean {
try {
new URL(text);
return true;
} catch {
return false;
}
}
saveBookmark(url: string) {
console.log('Creating bookmark for:', url);
// Implementation
}
createNote(text: string) {
console.log('Creating note with text:', text.substring(0, 50));
// Implementation
}
showNotification(message: string) {
console.log('Notification:', message);
// Show toast or notification
}
cleanup() {
if (this.listener) {
this.listener.remove();
}
}
}
// Usage
const shareTarget = new ShareTargetService();
shareTarget.initialize();
// Cleanup when app closes
// shareTarget.cleanup();
import { useEffect } from 'react';
import { CapacitorShareTarget } from '@capgo/capacitor-share-target';
function useShareTarget(onShareReceived: (event: any) => void) {
useEffect(() => {
const listener = CapacitorShareTarget.addListener('shareReceived', onShareReceived);
return () => {
listener.remove();
};
}, [onShareReceived]);
}
// Usage in component
function App() {
useShareTarget((event) => {
console.log('Share received:', event);
// Handle shared content
});
return <div>Your App</div>;
}
import { onMounted, onUnmounted } from 'vue';
import { CapacitorShareTarget } from '@capgo/capacitor-share-target';
export default {
setup() {
let listener: any;
onMounted(() => {
listener = CapacitorShareTarget.addListener('shareReceived', (event) => {
console.log('Share received:', event);
// Handle shared content
});
});
onUnmounted(() => {
if (listener) {
listener.remove();
}
});
}
};
if (event.texts && event.texts.length > 0) {
const text = event.texts[0];
if (text.startsWith('http://') || text.startsWith('https://')) {
// Handle URL
window.open(text, '_blank');
}
}
if (event.files) {
const images = event.files.filter(f => f.mimeType.startsWith('image/'));
images.forEach(async (image) => {
// Read and display image
const response = await fetch(image.uri);
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
// Display or process image
console.log('Image URL:', imageUrl);
});
}
if (event.files && event.files.length > 1) {
console.log(`Processing ${event.files.length} files`);
const processPromises = event.files.map(file =>
processFile(file)
);
await Promise.all(processPromises);
console.log('All files processed');
}
  1. 여러 콘텐츠 유형 처리: 텍스트, URL 및 파일을 받을 준비를 하세요.
  2. 콘텐츠 유효성 검사: 처리하기 전에 MIME 유형을 확인하세요.
  3. 피드백 제공: 사용자에게 받은 내용을 표시합니다.
  4. 오류 처리: 파일 URI가 유효하지 않거나 액세스할 수 없을 수 있습니다.
  5. 리스너 정리: 필요하지 않은 경우 리스너 제거
  6. 철저하게 테스트: 다양한 앱과 콘텐츠 유형으로 테스트하세요.
  7. 권한 요청: 일부 파일 형식에는 추가 권한이 필요할 수 있습니다.

Android에서 공유가 작동하지 않습니다.

Section titled “Android에서 공유가 작동하지 않습니다.”

android.intent.action.MAIN이 있는 <activity> 태그 내의 AndroidManifest.xml에 인텐트 필터가 올바르게 구성되어 있는지 확인하세요.

iOS 공유 확장 프로그램이 표시되지 않음

Section titled “iOS 공유 확장 프로그램이 표시되지 않음”
  1. 두 대상 모두에 앱 그룹이 구성되어 있는지 확인하세요.
  2. 공유 확장이 활성화되었는지 확인하세요.
  3. 공유 확장의 Info.plist 구성이 올바른지 확인하세요.
try {
const response = await fetch(file.uri);
const blob = await response.blob();
// Process blob
} catch (error) {
console.error('Failed to access file:', error);
// Show error to user
}
  • 전체 분석법 문서를 보려면 API 참조를 살펴보세요.
  • 고급 사용법은 예제 앱을 확인하세요.
  • 전체 구현 예는 튜토리얼을 참조하세요.