ACTION_SEND 의도에 대한 특정 앱 필터링 방법(앱별로 다른 텍스트 설정)
ACTION_SEND 의도를 사용할 때 특정 앱을 어떻게 걸러낼 수 있습니까?이 질문은 다양한 방식으로 제기되었지만, 저는 주어진 답변을 바탕으로 해결책을 찾지 못했습니다.누군가 도울 수 있기를 바랍니다.앱 내에서 공유할 수 있는 기능을 제공하고 싶습니다.Android Dev Alexander Lucas의 조언에 따라 Facebook/Twitter API를 사용하지 않고 의도를 사용하여 수행하고 싶습니다.
ACTION_SEND 의도를 사용하여 공유하는 것은 좋지만, 문제는 (1) 모든 공유 옵션이 거기에 있는 것이 아니라 FB, Twitter, Email로 제한하는 것이 낫다는 것이고, (2) 각 공유 앱에 동일한 것을 공유하고 싶지 않다는 것입니다.예를 들어, 제 트위터 공유에는 일부 언급과 해시태그가 140자 이하로 제한되어 있고, 페이스북 공유에는 링크와 기능 이미지가 포함되어 있습니다.
ACTION_SEND(공유) 의도에 대한 옵션을 제한할 수 있습니까?PackageManager 및 쿼리를 사용하는 방법을 보았습니다.활동을 의도하지만 패키지 관리자와 ACTION_SEND 의도 간의 연결을 파악하지 못했습니다.
OR
공유 앱을 필터링하는 것보다 ACTION_SEND 의도를 사용하여 대화상자가 뜨지 않고 직접 페이스북이나 트위터로 이동할 수 있다면 제 문제도 해결될 수 있습니다.만약 그렇다면, 저는 저만의 대화상자를 만들 수 있고, 그들이 "Facebook"을 클릭하면 Facebook 전용 의도를 만들어 Facebook으로 보낼 수 있습니다.트위터도 마찬가지입니다.
아니면 불가능한가요?페이스북과 트위터 API가 유일한 방법입니까?
나의 스펙은 사용자가 각각의 사용자 지정 텍스트가 포함된 이메일, 트위터, 페이스북 또는 SMS를 선택할 수 있도록 요구했습니다.이를 달성한 방법은 다음과 같습니다.
public void onShareClick(View v) {
Resources resources = getResources();
Intent emailIntent = new Intent();
emailIntent.setAction(Intent.ACTION_SEND);
// Native email client doesn't currently support HTML, but it doesn't hurt to try in case they fix it
emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_native)));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
emailIntent.setType("message/rfc822");
PackageManager pm = getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
Intent openInChooser = Intent.createChooser(emailIntent, resources.getString(R.string.share_chooser_text));
List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
for (int i = 0; i < resInfo.size(); i++) {
// Extract the label, append it, and repackage it in a LabeledIntent
ResolveInfo ri = resInfo.get(i);
String packageName = ri.activityInfo.packageName;
if(packageName.contains("android.email")) {
emailIntent.setPackage(packageName);
} else if(packageName.contains("twitter") || packageName.contains("facebook") || packageName.contains("mms") || packageName.contains("android.gm")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
if(packageName.contains("twitter")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_twitter));
} else if(packageName.contains("facebook")) {
// Warning: Facebook IGNORES our text. They say "These fields are intended for users to express themselves. Pre-filling these fields erodes the authenticity of the user voice."
// One workaround is to use the Facebook SDK to post, but that doesn't allow the user to choose how they want to share. We can also make a custom landing page, and the link
// will show the <meta content ="..."> text from that page with our link in Facebook.
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_facebook));
} else if(packageName.contains("mms")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_sms));
} else if(packageName.contains("android.gm")) { // If Gmail shows up twice, try removing this else-if clause and the reference to "android.gm" above
intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_gmail)));
intent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
intent.setType("message/rfc822");
}
intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
}
}
// convert intentList to array
LabeledIntent[] extraIntents = intentList.toArray( new LabeledIntent[ intentList.size() ]);
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);
}
저는 여러 곳에서 이것을 하는 방법의 일부를 찾았지만, 다른 곳에서는 그것을 모두 본 적이 없습니다.
이 방법은 또한 와이파이와 블루투스를 통한 공유와 같이 내가 원하지 않는 모든 어리석은 옵션을 숨깁니다.
편집: 코멘트에서, 저는 이 코드가 무엇을 하고 있는지 설명해 달라는 요청을 받았습니다.기본적으로, 그것은 그것을 만듭니다.ACTION_SEND
기본 전자 메일 클라이언트에만 사용할 수 있습니다. 그런 다음 다른 사용자를 선택기에 연결합니다. 의도를 되고, ACTION_SEND
선택기를 표시하기 전에 일반 텍스트 형식으로 고정합니다.
추가 인텐트를 가져올 때마다 사용자 지정 텍스트를 설정합니다.
Edit2: 이 글을 올린 지 꽤 됐는데, 상황이 좀 바뀌었습니다.옵션 목록에서 gmail이 두 번 표시되는 경우 아래 @h_k의 댓글에서 제안한 "android.gm "에 대한 특별한 처리를 제거해 보십시오.
이 한 가지 답변이 거의 모든 스택 오버플로 평판 포인트의 소스이기 때문에 적어도 최신 상태로 유지하려고 노력해야 합니다.
사용자 지정 옵션을 원하는 경우 이 작업에 대해 Android에서 제공하는 기본 대화 상자에 의존해서는 안 됩니다.
대신 여러분이 해야 할 일은 여러분 자신의 것을 출시하는 것입니다.패키지 관리자에게 요청한 작업을 처리하는 패키지를 쿼리한 다음 응답에 따라 필터링 및 사용자 정의된 텍스트를 적용해야 합니다.
구체적으로, 메소드 쿼리를 살펴봅니다.Package Manager 클래스의 Intent Activities입니다.기본 대화 상자(ACTION_SEND 의도)를 시작할 의도를 만들고 이를 이 메서드에 전달하면 해당 의도를 처리할 수 있는 활동에 대한 정보가 포함된 개체 목록을 받게 됩니다.그것을 이용해서, 당신은 당신이 원하는 것을 고를 수 있습니다.
표시할 패키지 목록을 작성한 후에는 해당 목록을 표시할 목록 대화상자(대화상자 테마가 있는 활동인 것이 좋습니다)를 작성해야 합니다.
그러나 한 가지 주의할 점은 사용자 지정 대화 상자를 기본 대화 상자처럼 만드는 것이 매우 어렵다는 것입니다.문제는 해당 대화 상자에서 사용되는 테마가 내부 테마이므로 응용 프로그램에서 사용할 수 없다는 것입니다.원하는 만큼 네이티브와 유사하게 만들거나 완전히 사용자 지정된 모양으로 만들 수 있습니다(많은 앱이 갤러리 앱 등과 같은 방식을 사용함).
여기서 확인할 수 있는 솔루션을 찾았습니다(첫 번째 답변의 세 번째 설명 참조).이 코드는 유효한 트위터 클라이언트를 찾고 이를 사용하여 트윗을 게시합니다.참고: 다양한 Twitter 클라이언트에 대한 의도를 제공하지 않으며 선택할 수도 있습니다.
트위터를 사용한 공유:
Intent shareIntent = findTwitterClient();
shareIntent.putExtra(Intent.EXTRA_TEXT, "test");
startActivity(Intent.createChooser(shareIntent, "Share"));
이 메서드 호출:
public Intent findTwitterClient() {
final String[] twitterApps = {
// package // name - nb installs (thousands)
"com.twitter.android", // official - 10 000
"com.twidroid", // twidroid - 5 000
"com.handmark.tweetcaster", // Tweecaster - 5 000
"com.thedeck.android" }; // TweetDeck - 5 000 };
Intent tweetIntent = new Intent();
tweetIntent.setType("text/plain");
final PackageManager packageManager = getPackageManager();
List<ResolveInfo> list = packageManager.queryIntentActivities(
tweetIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (int i = 0; i < twitterApps.length; i++) {
for (ResolveInfo resolveInfo : list) {
String p = resolveInfo.activityInfo.packageName;
if (p != null && p.startsWith(twitterApps[i])) {
tweetIntent.setPackage(p);
return tweetIntent;
}
}
}
return null;
}
Facebook은 "com.facebook.katana"를 사용하여 유사하지만 메시지 텍스트를 설정할 수는 없습니다(2011년 7월 사용되지 않음).
코드 소스: Android에서 Twitter 클라이언트를 열려고 합니다.
페이스북, 트위터, 카카오스토리 등 3가지 앱만 공유해보세요.
public void onShareClick(View v){
List<Intent> targetShareIntents=new ArrayList<Intent>();
Intent shareIntent=new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
List<ResolveInfo> resInfos=getPackageManager().queryIntentActivities(shareIntent, 0);
if(!resInfos.isEmpty()){
System.out.println("Have package");
for(ResolveInfo resInfo : resInfos){
String packageName=resInfo.activityInfo.packageName;
Log.i("Package Name", packageName);
if(packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana") || packageName.contains("com.kakao.story")){
Intent intent=new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Text");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.setPackage(packageName);
targetShareIntents.add(intent);
}
}
if(!targetShareIntents.isEmpty()){
System.out.println("Have Intent");
Intent chooserIntent=Intent.createChooser(targetShareIntents.remove(0), "Choose app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}else{
System.out.println("Do not Have Intent");
showDialaog(this);
}
}
}
@dacoinminster 덕분입니다.저는 인기 있는 앱의 패키지 이름과 앱의 정렬을 포함하여 그의 답변에 약간의 수정을 가했습니다.
List<Intent> targetShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> resInfos = pm.queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
System.out.println("Have package");
for (ResolveInfo resInfo : resInfos) {
String packageName = resInfo.activityInfo.packageName;
Log.i("Package Name", packageName);
if (packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana")
|| packageName.contains("com.whatsapp") || packageName.contains("com.google.android.apps.plus")
|| packageName.contains("com.google.android.talk") || packageName.contains("com.slack")
|| packageName.contains("com.google.android.gm") || packageName.contains("com.facebook.orca")
|| packageName.contains("com.yahoo.mobile") || packageName.contains("com.skype.raider")
|| packageName.contains("com.android.mms")|| packageName.contains("com.linkedin.android")
|| packageName.contains("com.google.android.apps.messaging")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.putExtra("AppName", resInfo.loadLabel(pm).toString());
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "https://website.com/");
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_text));
intent.setPackage(packageName);
targetShareIntents.add(intent);
}
}
if (!targetShareIntents.isEmpty()) {
Collections.sort(targetShareIntents, new Comparator<Intent>() {
@Override
public int compare(Intent o1, Intent o2) {
return o1.getStringExtra("AppName").compareTo(o2.getStringExtra("AppName"));
}
});
Intent chooserIntent = Intent.createChooser(targetShareIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
} else {
Toast.makeText(getActivity(), "No app to share.", Toast.LENGTH_LONG).show();
}
}
당신은 아래 코드를 사용해 볼 수 있습니다, 완벽하게 작동합니다.
여기서는 Facebook, Messenger, Twitter, Google Plus 및 Gmail과 같은 특정 앱을 공유합니다.
public void shareIntentSpecificApps() {
List<Intent> intentShareList = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(shareIntent, 0);
for (ResolveInfo resInfo : resolveInfoList) {
String packageName = resInfo.activityInfo.packageName;
String name = resInfo.activityInfo.name;
Log.d(TAG, "Package Name : " + packageName);
Log.d(TAG, "Name : " + name);
if (packageName.contains("com.facebook") ||
packageName.contains("com.twitter.android") ||
packageName.contains("com.google.android.apps.plus") ||
packageName.contains("com.google.android.gm")) {
if (name.contains("com.twitter.android.DMActivity")) {
continue;
}
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Your Content");
intentShareList.add(intent);
}
}
if (intentShareList.isEmpty()) {
Toast.makeText(MainActivity.this, "No apps to share !", Toast.LENGTH_SHORT).show();
} else {
Intent chooserIntent = Intent.createChooser(intentShareList.remove(0), "Share via");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentShareList.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
}
이 솔루션은 ListView 대화상자에 선택기와 유사한 응용프로그램 목록을 표시합니다.
다음과 같은 작업을 수행할 수 있습니다.
- 관련 응용 프로그램 패키지 목록 가져오기
- 패키지 이름을 지정하면 관련 의도를 호출합니다.
어댑터 클래스:
import java.util.List;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class ChooserArrayAdapter extends ArrayAdapter<String> {
PackageManager mPm;
int mTextViewResourceId;
List<String> mPackages;
public ChooserArrayAdapter(Context context, int resource, int textViewResourceId, List<String> packages) {
super(context, resource, textViewResourceId, packages);
mPm = context.getPackageManager();
mTextViewResourceId = textViewResourceId;
mPackages = packages;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String pkg = mPackages.get(position);
View view = super.getView(position, convertView, parent);
try {
ApplicationInfo ai = mPm.getApplicationInfo(pkg, 0);
CharSequence appName = mPm.getApplicationLabel(ai);
Drawable appIcon = mPm.getApplicationIcon(pkg);
TextView textView = (TextView) view.findViewById(mTextViewResourceId);
textView.setText(appName);
textView.setCompoundDrawablesWithIntrinsicBounds(appIcon, null, null, null);
textView.setCompoundDrawablePadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getContext().getResources().getDisplayMetrics()));
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return view;
}
}
및 그 용도:
void doXxxButton() {
final List<String> packages = ...;
if (packages.size() > 1) {
ArrayAdapter<String> adapter = new ChooserArrayAdapter(MyActivity.this, android.R.layout.select_dialog_item, android.R.id.text1, packages);
new AlertDialog.Builder(MyActivity.this)
.setTitle(R.string.app_list_title)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item ) {
invokeApplication(packages.get(item));
}
})
.show();
} else if (packages.size() == 1) {
invokeApplication(packages.get(0));
}
}
void invokeApplication(String packageName) {
// given a package name, create an intent and fill it with data
...
startActivityForResult(intent, rq);
}
가장 깨끗한 방법은 다음 클래스를 복사하는 것입니다.Share Action Provider, Activity Chooser View, Activity Chooser Model을 선택합니다.활동 선택기 모델에서 의도를 필터링하는 기능과 ShareActionProvider에서 적절한 지원 방법을 추가합니다.필요한 클래스를 만들었습니다. 프로젝트(https://gist.github.com/saulpower/10557956) 에 복사할 수 있습니다.이렇게 하면 공유할 앱을 필터링할 수 있을 뿐만 아니라(패키지 이름을 알고 있는 경우) 기록을 끌 수도 있습니다.
private final String[] INTENT_FILTER = new String[] {
"com.twitter.android",
"com.facebook.katana"
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.journal_entry_menu, menu);
// Set up ShareActionProvider's default share intent
MenuItem shareItem = menu.findItem(R.id.action_share);
if (shareItem instanceof SupportMenuItem) {
mShareActionProvider = new ShareActionProvider(this);
mShareActionProvider.setShareIntent(ShareUtils.share(mJournalEntry));
mShareActionProvider.setIntentFilter(Arrays.asList(INTENT_FILTER));
mShareActionProvider.setShowHistory(false);
((SupportMenuItem) shareItem).setSupportActionProvider(mShareActionProvider);
}
return super.onCreateOptionsMenu(menu);
}
저는 @dacoinminster 답변을 개선했고 이것은 당신의 앱을 공유하기 위한 예시와 함께 나온 결과입니다.
// Intents with SEND action
PackageManager packageManager = context.getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(sendIntent, 0);
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
Resources resources = context.getResources();
for (int j = 0; j < resolveInfoList.size(); j++) {
ResolveInfo resolveInfo = resolveInfoList.get(j);
String packageName = resolveInfo.activityInfo.packageName;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setComponent(new ComponentName(packageName,
resolveInfo.activityInfo.name));
intent.setType("text/plain");
if (packageName.contains("twitter")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.twitter) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
} else {
// skip android mail and gmail to avoid adding to the list twice
if (packageName.contains("android.email") || packageName.contains("android.gm")) {
continue;
}
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForFacebookWhatsapp) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
}
intentList.add(new LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon));
}
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.subjectForMailApps));
emailIntent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForMailApps) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
context.startActivity(Intent.createChooser(emailIntent, resources.getString(R.string.compartirEn)).putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new LabeledIntent[intentList.size()])));
저도 같은 문제가 있었지만 이 수락된 솔루션은 도움이 되지 않았습니다. 누군가가 같은 문제를 가지고 있다면 제 코드 조각을 사용할 수 있습니다.
// example of filtering and sharing multiple images with texts
// remove facebook from sharing intents
private void shareFilter(){
String share = getShareTexts();
ArrayList<Uri> uris = getImageUris();
List<Intent> targets = new ArrayList<>();
Intent template = new Intent(Intent.ACTION_SEND_MULTIPLE);
template.setType("image/*");
List<ResolveInfo> candidates = getActivity().getPackageManager().
queryIntentActivities(template, 0);
// remove facebook which has a broken share intent
for (ResolveInfo candidate : candidates) {
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.facebook.katana")) {
Intent target = new Intent(Intent.ACTION_SEND_MULTIPLE);
target.setType("image/*");
target.putParcelableArrayListExtra(Intent.EXTRA_STREAM,uris);
target.putExtra(Intent.EXTRA_TEXT, share);
target.setPackage(packageName);
targets.add(target);
}
}
Intent chooser = Intent.createChooser(targets.remove(0), "Share Via");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
startActivity(chooser);
}
Intent emailIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("mailto", "android@gmail.com", null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, text);
startActivity(Intent.createChooser(emailIntent, "Send email..."));
너무 단순하고 간결합니다.오픈 소스 개발자 덕분에 이 솔루션을 공유해 준 cketti:
String mailto = "mailto:bob@example.org" +
"?cc=" + "alice@example.com" +
"&subject=" + Uri.encode(subject) +
"&body=" + Uri.encode(bodyText);
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));
try {
startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
//TODO: Handle case where no email app is available
}
그리고 이것이 그/그녀의 요지에 대한 링크입니다.
언급URL : https://stackoverflow.com/questions/9730243/how-to-filter-specific-apps-for-action-send-intent-and-set-a-different-text-for
'programing' 카테고리의 다른 글
조인 마리애드브 제한 수 (0) | 2023.08.29 |
---|---|
C++ 문자열에서 상수가 아닌 C 문자열을 다시 받을 수 있습니까? (0) | 2023.08.29 |
패스트리 키트 프레임워크란 무엇입니까? (0) | 2023.08.29 |
Ubuntu에 Galera Manger를 설치할 수 없습니다. (0) | 2023.08.29 |
MariaDB가 MySQL이나 Percona보다 SQL을 즉시 가져오는 속도가 빠른 이유는 무엇입니까? (0) | 2023.08.29 |