Wednesday, June 19, 2024
HomeiOS Developmentios - Unable to Share Picture to TikTok from Flutter App Because...

ios – Unable to Share Picture to TikTok from Flutter App Because of “Permissions Denied” Error


I am attempting to share a picture from my Flutter app to TikTok utilizing the TikTok Open SDK and share sdk. I’ve built-in the TikTok SDK into my iOS undertaking.
I am encountering the next error when making an attempt to share:

[FirebaseAnalytics][I-ACS023001] Deep Hyperlink doesn't comprise legitimate required params. URL params: {
    "error_code" = "-4";
    "error_description" = "Permissions denied";
    "from_platform" = tiktoksharesdk;
    "request_id" = "B0AC02F2-33CE-4C94-8F47-9ABF3381CB90";
    "response_id" = "40AA3C41-DC79-4026-9D41-D627931EAE1F";
    "share_state" = 20003;
}

I’ve tried some options i discovered on-line like including the Login package, convert the native file path to PHAsset, checked podfile, made certain the app was accepted on tiktok dev web site, added the keys to plist file…

Beneath are the related code snippets from my AppDelegate.swift and Flutter code. Can somebody assist me determine what may be going improper?

import UIKit
import Flutter
import TikTokOpenSDKCore
import TikTokOpenShareSDK
import Photographs

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func utility(
        _ utility: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)

        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(identify: "com.instance.tiktokshare/share",
                                           binaryMessenger: controller.binaryMessenger)

        channel.setMethodCallHandler { [weak self] (name, outcome) in
            if name.methodology == "shareImage" {
                if let args = name.arguments as? [String: Any], let localIdentifiers = args["localIdentifiers"] as? [String] {
                    TikTokShare().shareImage(localIdentifiers: localIdentifiers, outcome: outcome)
                } else {
                    outcome(FlutterError(code: "error", message: "Invalid arguments", particulars: nil))
                }
            } else if name.methodology == "getLocalIdentifier" {
                if let args = name.arguments as? [String: Any], let filePath = args["filePath"] as? String {
                    self?.getLocalIdentifier(for: filePath, outcome: outcome)
                } else {
                    outcome(FlutterError(code: "error", message: "Invalid arguments", particulars: nil))
                }
            } else {
                outcome(FlutterMethodNotImplemented)
            }
        }

        return tremendous.utility(utility, didFinishLaunchingWithOptions: launchOptions)
    }

    non-public func getLocalIdentifier(for filePath: String, outcome: @escaping FlutterResult) {
        let standing = PHPhotoLibrary.authorizationStatus()
        if standing == .notDetermined {
            PHPhotoLibrary.requestAuthorization { newStatus in
                if newStatus == .licensed {
                    self.saveToPhotoLibrary(filePath: filePath, outcome: outcome)
                } else {
                    outcome(FlutterError(code: "error", message: "Photographs permission denied", particulars: nil))
                }
            }
        } else if standing == .licensed {
            self.saveToPhotoLibrary(filePath: filePath, outcome: outcome)
        } else {
            outcome(FlutterError(code: "error", message: "Photographs permission denied", particulars: nil))
        }
    }

    non-public func saveToPhotoLibrary(filePath: String, outcome: @escaping FlutterResult) {
        var localIdentifier: String?

        PHPhotoLibrary.shared().performChanges({
            let request: PHAssetChangeRequest?
            if filePath.hasSuffix(".jpeg") || filePath.hasSuffix(".jpg") || filePath.hasSuffix(".png") {
                request = PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: URL(fileURLWithPath: filePath))
            } else {
                request = nil
            }
            localIdentifier = request?.placeholderForCreatedAsset?.localIdentifier
        }, completionHandler: { success, error in
            if success, let localIdentifier = localIdentifier {
                outcome([localIdentifier])
            } else {
                outcome(FlutterError(code: "error", message: "Did not get native identifier", particulars: error?.localizedDescription))
            }
        })
    }
}

@objc(TikTokShare)
class TikTokShare: NSObject {
    @objc func shareImage(localIdentifiers: [String], outcome: @escaping FlutterResult) {
        let shareRequest = TikTokShareRequest(localIdentifiers: localIdentifiers,
                                              mediaType: .picture,
                                              redirectURI: "revamped://tiktokshare")
        shareRequest.shareFormat = .regular
        shareRequest.ship { response in
            guard let shareResponse = response as? TikTokShareResponse else {
                outcome(FlutterError(code: "error", message: "Invalid response", particulars: nil))
                return
            }
            if shareResponse.errorCode == .noError {
                outcome("Share succeeded!")
            } else {
                outcome(FlutterError(code: "error", message: "Share failed with error code: (shareResponse.errorCode.rawValue), state: (shareResponse.shareState)", particulars: nil))
            }
        }
    }
}

Flutter code:

import 'bundle:flutter/companies.dart';
import 'bundle:image_picker/image_picker.dart';
import 'bundle:permission_handler/permission_handler.dart';

class TikTokShare {
  static const MethodChannel _channel =
      MethodChannel('com.instance.tiktokshare/share');

  static Future<Record<String>> getLocalIdentifier(String filePath) async {
    strive {
      ultimate Record<dynamic> outcome = await _channel
          .invokeMethod('getLocalIdentifier', {'filePath': filePath});
      return outcome.forged<String>();
    } on PlatformException catch (e) {
      print("Did not get native identifier: '${e.message}'.");
      return [];
    }
  }

  static Future<void> shareImage(Record<String> localIdentifiers) async {
    strive {
      ultimate outcome = await _channel
          .invokeMethod('shareImage', {'localIdentifiers': localIdentifiers});
      print(outcome);
    } on PlatformException catch (e) {
      print("Did not share picture: '${e.message}'.");
    }
  }
}

void shareToTikTok() async {
  print("Sharing to TikTok...");

  var standing = await Permission.photographs.request();

  if (standing.isGranted) {
    ultimate picker = ImagePicker();
    ultimate pickedFile = await picker.pickImage(supply: ImageSource.gallery);

    if (pickedFile != null) {
      ultimate filePath = pickedFile.path;
      ultimate Record<String> localIdentifiers =
          await TikTokShare.getLocalIdentifier(filePath);
      if (localIdentifiers.isNotEmpty) {
        TikTokShare.shareImage(localIdentifiers);
      } else {
        print("Did not get native identifier.");
      }
    } else {
      print("No picture chosen.");
    }
  } else {
    print("Photographs permission denied.");
  }
}



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments