반응형

 

앱에서

let securityCodeTextField = UITextField()
securityCodeTextField.textContentType = .oneTimeCode

UITextContentType을  oneTimeCode로 지정할 경우

SMS 메시지가 왔을때 "code"또는 "passcode"라는 단어가 포함 된 메시지에서 자동으로 확인 코드를 감지합니다

 

웹에서

<input id="single-factor-code-text-field" autocomplete="one-time-code"/>

 

반응형

'IOS' 카테고리의 다른 글

(IOS)WKWebview 앱캐시 문제  (1) 2020.02.26
(IOS)wkwebview 적용해보기  (0) 2020.01.31
(IOS) 토스트 만들기 - objective-c  (0) 2020.01.22
(IOS)스토리보드에서 VIEW 관리하기  (0) 2020.01.21
(IOS)날짜 비교  (0) 2020.01.14
반응형

성격급한분들을 위한 완성본

만들기

#import <UIKit/UIKit.h>

@interface FSToast : UIView

+(void)showToast:(UIViewController*)vc messge:(NSString*)message;
+(void)showToast:(UIViewController *)vc messge:(NSString *)message backgroundColor:(UIColor*)backgroundColor duration:(int)duration;

+(void)createToast:(UIViewController *)vc messge:(NSString *)message;
+(void)createToast:(UIViewController *)vc messge:(NSString *)message backgroundColor:(UIColor*)backgroundColor duration:(int)duration;

@end
#import "FSToast.h"

typedef enum { R, G, B, A } UIColorComponentIndices;

@implementation UIColor (EPPZKit)

-(CGFloat)red
{ return CGColorGetComponents(self.CGColor)[0]; }

-(CGFloat)green
{ return CGColorGetComponents(self.CGColor)[1]; }

-(CGFloat)blue
{ return CGColorGetComponents(self.CGColor)[2]; }

-(CGFloat)alpha
{ return CGColorGetComponents(self.CGColor)[3]; }

@end


@interface FSToast (){
    
}

@end

@implementation FSToast

+(void)showToast:(UIViewController *)vc messge:(NSString *)message {
    NSLog(@"## test : %@",message);
    [self createToast:vc messge:message];
    
}

+(void)showToast:(UIViewController *)vc messge:(NSString *)message backgroundColor:(UIColor*)backgroundColor duration:(int)duration{
    NSLog(@"## test : %@",message);
    [self createToast:vc messge:message backgroundColor:backgroundColor duration:duration];
    
}

+(void)createToast:(UIViewController *)vc messge:(NSString *)message{
    //location
    CGFloat paddingToastLB = 20; //string 사이즈에 추가적인 여유공간.
    CGFloat transitionY = 25; // 애니매이션시 이동할 y축 거리
    CGRect mainbounds = UIScreen.mainScreen.bounds;
    UIFont *toastFont = [UIFont systemFontOfSize:12];
    CGSize tempSize = [self getStringSizeWithText:message font:toastFont];
    

    CGFloat toastwidth = tempSize.width+paddingToastLB;
    CGFloat toastheight = tempSize.height+paddingToastLB;
    
    /*
         (메인스크린/2) - (토스트/2)
        ,(메인스크린/2) - (토스트/2) - (애니메이션 움직일 거리)
        , 토스트
        , 토스트
     */
    CGRect tempRect = CGRectMake((mainbounds.size.width/2)-(toastwidth/2), (mainbounds.size.height/2)-(toastheight/2)-transitionY, toastwidth, toastheight);
    
    //design
    __block UILabel* toastMsgLB = nil;
    toastMsgLB = [[UILabel alloc] initWithFrame:tempRect];
    toastMsgLB.backgroundColor = [UIColor.whiteColor colorWithAlphaComponent:0.95];
    toastMsgLB.textAlignment = NSTextAlignmentCenter;
    toastMsgLB.textColor = UIColor.blackColor;
    [toastMsgLB setText:message];
    [toastMsgLB setFont:toastFont];
    toastMsgLB.numberOfLines = 0;
    
    //layer
    //round
    [self addShadowLayer:toastMsgLB];
    [vc.view addSubview:toastMsgLB];
    
    //animation
    toastMsgLB.alpha = 0.0;
    CGRect transitionRect = CGRectMake(tempRect.origin.x, tempRect.origin.y+transitionY, tempRect.size.width, tempRect.size.height);
    [UIView animateWithDuration:0.5 animations:^{
         toastMsgLB.alpha = 1.0;
         toastMsgLB.frame = transitionRect;
    } completion:^(BOOL finished) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [UIView animateWithDuration:0.3 animations:^{
                toastMsgLB.alpha = 0.0;
                toastMsgLB.transform = CGAffineTransformMakeScale(0.01, 0.01);
            } completion:^(BOOL finished) {
                [toastMsgLB removeFromSuperview];
                toastMsgLB = nil;
            }];
        });
    }];
}

+(void)createToast:(UIViewController *)vc messge:(NSString *)message backgroundColor:(UIColor*)backgroundColor duration:(int)duration{
    //location
    CGFloat paddingToastLB = 20;
    CGFloat transitionY = 25;
    CGRect mainbounds = UIScreen.mainScreen.bounds;
    UIFont *taostFont = [UIFont systemFontOfSize:12];
    CGSize tempSize = [self getStringSizeWithText:message font:taostFont];
    
    CGFloat toastwidth = tempSize.width+paddingToastLB;
    CGFloat toastheight = tempSize.height+paddingToastLB;

    CGRect tempRect = CGRectMake((mainbounds.size.width/2)-(toastwidth/2), (mainbounds.size.height/2)-(toastheight/2)-transitionY, toastwidth, toastheight);
    
//    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
//    nf.roundingMode = NSNumberFormatterRoundFloor;
//    nf.minimumSignificantDigits = 10;
//    NSLog(@"## red :%f ,blue : %f,green : %f",[backgroundColor red],[backgroundColor blue],[backgroundColor green]);
    
    //design
    __block UILabel* toastMsgLB = nil;
    toastMsgLB = [[UILabel alloc] initWithFrame:tempRect];
    toastMsgLB.backgroundColor = backgroundColor;
    toastMsgLB.textAlignment = NSTextAlignmentCenter;
    toastMsgLB.textColor = UIColor.whiteColor;
    [toastMsgLB setText:message];
    [toastMsgLB setFont:taostFont];
    toastMsgLB.numberOfLines = 0;
    
    //layer
    //round
    [self addShadowLayer:toastMsgLB];
    [vc.view addSubview:toastMsgLB];
    
    //animation
    toastMsgLB.alpha = 0.0;
    CGRect transitionRect = CGRectMake(tempRect.origin.x, tempRect.origin.y+transitionY, tempRect.size.width, tempRect.size.height);
    [UIView animateWithDuration:0.5 animations:^{
         toastMsgLB.alpha = 1.0;
         toastMsgLB.frame = transitionRect;
    } completion:^(BOOL finished) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [UIView animateWithDuration:0.3 animations:^{
                toastMsgLB.alpha = 0.0;
                toastMsgLB.transform = CGAffineTransformMakeScale(0.01, 0.01);
            } completion:^(BOOL finished) {
                [toastMsgLB removeFromSuperview];
                toastMsgLB = nil;
            }];
        });
    }];
}

//string size를 미리계산해 반환한다.
+(CGSize)getStringSizeWithText:(NSString *)string font:(UIFont *)font{
    UILabel *label = [[UILabel alloc] init];
    label.text = string;
    label.font = font;
    return label.attributedText.size;
}

//그림자를 넣어준다.
//둥그렇게 해주고싶었지만 어떻게 하는지 모르겟다...
+(void)addShadowLayer:(UIView*)v {
    //layer
    //round
    v.layer.masksToBounds = false;
    v.layer.cornerRadius = 15;
    //border
    v.layer.borderColor = UIColor.clearColor.CGColor;
    v.layer.borderWidth = 1.0;
    //shadow
    v.layer.shadowColor = UIColor.blackColor.CGColor;
    v.layer.shadowOffset = CGSizeMake(2.0, 2.0);
    v.layer.shadowOpacity = 0.4;
    v.layer.shadowRadius = 3.5;
}

@end

 

사용

[FSToast showToast:self messge:@"test !! 1234 124 :Adowefhanweofpin2po3qfinasdfdsflkansdf"];
[FSToast showToast:self 
		messge:@"test !! 1234 124 :\nAdowefhanweofpin2po3qfinasdfdsflkansdf" 
		backgroundColor:UIColor.blueColor 
		duration:1];

응용(복사뒤 토스트)

 

NSString *cpnNO =@"복사할 대상 택스트입니다 ...... ";
UIPasteboard *pb = [UIPasteboard generalPasteboard];
[pb setString:cpnNO];
[FSToast showToast:self messge:cpnNO];

직접 만들어보기

일단은 보여질 view를 구성 스크린 사이즈중 가운데를 알아야한다.

 CGRect mainbounds = UIScreen.mainScreen.bounds;

 

반응형

'IOS' 카테고리의 다른 글

(IOS)wkwebview 적용해보기  (0) 2020.01.31
(IOS)sms로 인증문자 받아서 keyboard위에 띄우기  (0) 2020.01.30
(IOS)스토리보드에서 VIEW 관리하기  (0) 2020.01.21
(IOS)날짜 비교  (0) 2020.01.14
[IOS]custom bottom sheet  (0) 2019.12.31
반응형

기본준비

 

- 옆쪽 여러 컨트롤러들이랑 storyboard의 각 controller를 연결 시켜주었다.

 

 

-이런식으로 연결해주면된다.

 

 

만들어주기

import Foundation

extension NSObject {
  public var className: String {
    return String(describing: type(of: self)).components(separatedBy: ".").last!
  }
  
  public class var className: String {
    return String(describing: self).components(separatedBy: ".").last!
  }
}

- 클래스명을 편하게 가저올수있도록 extension으로 하나빼준다.

import UIKit

enum CMStory : Int {
    public struct Board {
      public static let main = "Main"
    }
    case main = 0
    case permission = 1
    
    static func create(_ scene: UIWindowScene ,type: CMStory, navBar: Bool = true, board: String = CMStory.Board.main) -> UIWindow {
      switch type {
          case .main: return CMStroyBoard.createWindow( scene, boardId: board, viewId: MainView.className, navigationBar: navBar)
          case .permission: return CMStroyBoard.createWindow( scene, boardId: board, viewId: PermissionView.className, navigationBar: navBar)
        }
    }
}

- 바로 window 객체를 리턴해줄수있도록 생성해준다.

import UIKit

public final class CMStroyBoard {
     //storyboard
    public static func createWindow(_ scene: UIWindowScene,
    boardId: String, 
    viewId: String,
    navigationBar: Bool = false) -> UIWindow {
                                    
      let window: UIWindow = UIWindow(frame: UIScreen.main.bounds)// window가 없으니 만들어준다.
      let mainBoard = UIStoryboard(name: boardId, bundle: nil)// 스토리보드 인스턴스
      let vc = mainBoard.instantiateViewController(withIdentifier: viewId)//뷰 컨트롤러 인스턴스
      if navigationBar == true {
        window.rootViewController = UINavigationController(rootViewController: vc)
      }else{
        window.rootViewController = vc// 윈도우의 루트 뷰 컨트롤러 설정
      }
      window.windowScene = scene
      window.makeKeyAndVisible()
      
      return window
    }
    
    //no storyboard
    public static func createWindow(_ scene: UIWindowScene,
   			 vc: UIViewController,
    		navigationBar: Bool = false) -> UIWindow {
      let window: UIWindow = UIWindow(frame: UIScreen.main.bounds)
      if navigationBar == true {
        window.rootViewController = UINavigationController(rootViewController: vc)
      }else{
        window.rootViewController = vc
      }
      window.windowScene = scene
      window.makeKeyAndVisible()
      
      return window
    }
    
    public static func createViewController(viewId: String) -> UIViewController {
      let boardId:String = CMStory.Board.main
      let mainBoard = UIStoryboard(name: boardId, bundle: nil)// 스토리보드 인스턴스
      let vc = mainBoard.instantiateViewController(withIdentifier: viewId)
      return vc
    }
}

 

- window 객체에 rootcontroller를 넘겨준 viewID 로 컨트롤러를찾아 지정해준다.

- createViewController에서 매번 스토리보드를 호출할필요없게 따로 uiviewcontroller를 리턴하게 만들어준다.

 

사용

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene,
    			willConnectTo session: UISceneSession,
    			options connectionOptions: UIScene.ConnectionOptions) {
        guard let sc = (scene as? UIWindowScene) else { return }
        window = CMStory.create(sc, type: .permission, navBar : true)
    }
		....


}

- 간결하게 root controller를 enum 타입으로 호출할수있다.

 

let myvc = CMStroyBoard.createViewController(viewId: LoginView.className) as! LoginView
self.push(viewController: myvc)

- 이런식으로 바로 가저와 uiviewController객체를 사용할수있다.

- 메모리관리에 좋은지는 테스트가 필요하다.

반응형
반응형

만들기

    private fun shareURL(strJson:String){
        val a: ShareUrlVO = Gson().fromJson(strJson, ShareUrlVO::class.java)
        val i = Intent(Intent.ACTION_SEND)
        i.setType("text/plain")
        i.putExtra(Intent.EXTRA_SUBJECT,a.chooserTitle)// 공유했을때 제목
        i.putExtra(Intent.EXTRA_TEXT,a.url)//링크 url
        startActivity(Intent.createChooser(i, a.subject)); // 위 그림에 나오는 제목부분
    }
class ShareUrlVO {
    constructor()
    constructor(chooserTitle: String, subject: String, url: String) {
        this.chooserTitle = chooserTitle
        this.subject = subject
        this.url = url
    }
    var chooserTitle: String = ""
    var subject: String = ""
    var url: String = ""
}

 

사용

 val str:String = "{\n" +
         "  \"chooserTitle\": \"\\\"선택 타이틀\\\"\",\n" +
         "  \"subject\": \"\\\"제목\\\"\",\n" +
         "  \"url\": \"\\\"https://www.naver.com\\\"\"\n" +
         "}"
         
         
shareURL(str)

-참고 : https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents

반응형
반응형

타입을 정의하기위한 enum class

// Container Activity must implement this interface
enum class FragmentType{
    PERMISSION, COUPON,HOME,LOGIN,SEARCH,SIGNUP
}
​

다른 클래스에도 사용할수있는 interface

interface MainInterface {
    fun onMainInterface(str:String)
    fun onMoveFragment(type: FragmentType ,animate:Boolean = true)
}

 

class MainActivity : AppCompatActivity() ,MainInterface {

    private var counts:Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        onMoveFragment(FragmentType.PERMISSION,false)
    }
}

 

    /**
     * @Type: MainInterface
     */
    override fun onMoveFragment(type: FragmentType, animate: Boolean) {
        when (type) {
            FragmentType.HOME -> changeFragment(HomeFragment.newInstance(index = counts),animate)
            FragmentType.COUPON -> changeFragment(CouponFragment.newInstance(index = counts),animate)
            FragmentType.LOGIN -> changeFragment(LoginFragment.newInstance(index = counts),animate)
            FragmentType.SEARCH -> changeFragment(SearchFragment.newInstance(index = counts),animate)
            FragmentType.SIGNUP -> changeFragment(SignupFragment.newInstance(index = counts),animate)
            FragmentType.PERMISSION -> changeFragment(PermissionFragment.newInstance(index = counts),animate)
        }
    }
    private fun changeFragment(f : Fragment, animate:Boolean){
        val fm = supportFragmentManager
        val t = fm.beginTransaction()
        t.replace(R.id.mainFrame, f)
        if (animate)
            t.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right)

        t.addToBackStack(null)
        t.commit()
        counts++
    }

 

반응형
반응형

비교

    func isExpired(expiredDate:Int)->Bool{
        var isep : Bool = false
        
        let currentTime : String = Date.string(fmt: .standard)
        let prevTime : String = "2020-01-14 11:11:11"
        
        if (!currentTime.isEmpty && !prevTime.isEmpty){
            let ct:Date = Date.stringToDate(currentTime)
            let pt:Date = Date.stringToDate(prevTime)
            let tis = Int(ct.timeIntervalSince(pt)/(60*60*24))
            if tis >= expiredDate {
                isep = true
            }
        }
        return isep
    }

 

- Date.string 부분과 Date.stringToDate는 expentension으로 빼놨다.

- timeIntervalSince로 두 날짜의 차이를 구한뒤 60*60*24(하루) 으로 나눠준다 , 둘차이가 하루가안되면 0일것이다.

 

유틸펑션

extension Date {
    enum DateFormat {
      case standard
    }
	//지정된 포맷으로 현재 날짜 string으로 반환
    static func string(fmt: DateFormat) -> String {
      let formatter = DateFormatter()
      switch fmt {
      case .standard:
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.string(from: Date())
      default:
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.string(from: Date())
      }
    }
    
    //string date를 timezon UTC 방식으로 변환
    static func stringToDate(_ stringDate: String) -> (Date) {
        let formatter = DateFormatter()
        formatter.dateFormat =  "yyyy-MM-dd HH:mm:ss"
        formatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?
        return formatter.date(from: stringDate)!
    }
    
}

-필요에 따라 포맷형식이나 타임존 방식을 변경해서 사용하면된다.

사용

if isExpired(30) {
	//지난 날짜.
}
else {
	//아직 안지남
}
반응형
반응형

클래스 만들기

import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import java.lang.reflect.Method;
import java.util.List;

public final class TelephonyInfo {

    private static final String TAG = "TelephonyInfo";
    private static TelephonyInfo telephonyInfo;
    private String imeiSIM1;
    private String imeiSIM2;
    private boolean isSIM1Ready;
    private boolean isSIM2Ready;

    public String getImsiSIM1() {
        return imeiSIM1;
    }

    public String getImsiSIM2() {
        return imeiSIM2;
    }

    public boolean isSIM1Ready() {
        return isSIM1Ready;
    }

    public boolean isSIM2Ready() {
        return isSIM2Ready;
    }

    public boolean isDualSIM() {
        return imeiSIM2 != null;
    }

    private TelephonyInfo() { }

    /*
    * 생성.
    * */
    public static TelephonyInfo getInstance(Context context){

        if(telephonyInfo == null) {

            telephonyInfo = new TelephonyInfo();

            TelephonyManager telephonyManager = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));

            telephonyInfo.imeiSIM1 = telephonyManager.getDeviceId();;
            telephonyInfo.imeiSIM2 = null;

            /*
              get Device id
            */
            String[] methods = {"getDeviceIdGemini","getDeviceId","getDeviceIdDs","getSimSerialNumberGemini"};
            boolean success = false;
            for(int i=0; i < methods.length; i++) {
                try {
                    telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, methods[i], 0);
                    telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, methods[i], 1);
                    success = true;
                } catch(GeminiMethodNotFoundException e) {
                  
                }
                if (success) break;
            }
            

            /*
               sim state
            */
            telephonyInfo.isSIM1Ready = telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
            telephonyInfo.isSIM2Ready = false;

            String[] simMethods = {"getSimStateGemini","getSimState"};
            boolean success2 = false;
            for(int i=0; i < simMethods.length; i++) {
                try {
                    telephonyInfo.isSIM1Ready = getSIMStateBySlot(context,  simMethods[i], 0);
                    telephonyInfo.isSIM2Ready = getSIMStateBySlot(context,  simMethods[i], 1);
                    success2 = true;
                } catch(GeminiMethodNotFoundException e) {
                    
                }
                if (success2) break;
            }

            printTelephonyManagerMethodNamesForThisDevice(context);
        }

        return telephonyInfo;
    }

    /*
    * 슬롯의 device id를 가저온다.
    * */
    private static String getDeviceIdBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {

        String imei = null;

        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        try{

            Class<?> telephonyClass = Class.forName(telephony.getClass().getName());

            Class<?>[] parameter = new Class[1];
            parameter[0] = int.class;
            Method getSimID = telephonyClass.getMethod(predictedMethodName, parameter);

            Object[] obParameter = new Object[1];
            obParameter[0] = slotID;
            Object ob_phone = getSimID.invoke(telephony, obParameter);

            if(ob_phone != null){
                imei = ob_phone.toString();

            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new GeminiMethodNotFoundException(predictedMethodName);
        }

        return imei;
    }

    /*
    * slot에 sim상태를 가저온다.
    * */
    private static  boolean getSIMStateBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {

        boolean isReady = false;

        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        try{

            Class<?> telephonyClass = Class.forName(telephony.getClass().getName());

            Class<?>[] parameter = new Class[1];
            parameter[0] = int.class;
            Method getSimStateGemini = telephonyClass.getMethod(predictedMethodName, parameter);

            Object[] obParameter = new Object[1];
            obParameter[0] = slotID;
            Object ob_phone = getSimStateGemini.invoke(telephony, obParameter);

            if(ob_phone != null){
                int simState = Integer.parseInt(ob_phone.toString());
                if(simState == TelephonyManager.SIM_STATE_READY){
                    isReady = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new GeminiMethodNotFoundException(predictedMethodName);
        }

        return isReady;
    }


    private static class GeminiMethodNotFoundException extends Exception {

        private static final long serialVersionUID = -996812356902545308L;

        public GeminiMethodNotFoundException(String info) {
            super(info);
        }
    }
    /*
    * 리플랙트로 가저온 모든 method명을 프린트한다.
    * */
    public static void printTelephonyManagerMethodNamesForThisDevice(Context context) {

        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        Class<?> telephonyClass;
        try {
            telephonyClass = Class.forName(telephony.getClass().getName());
            Method[] methods = telephonyClass.getMethods();
            for (int idx = 0; idx < methods.length; idx++) {
                ELog.i("## " + methods[idx] + " declared by " + methods[idx].getDeclaringClass());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /*
     * dual sim 번호를 가저온다.
     * */

    public static String getDualSimNumber(Context context){
        String number = null;
        TelephonyInfo ti =TelephonyInfo.getInstance(context);

        boolean isSIM1Ready = ti.isSIM1Ready();//1번 장착
        boolean isSIM2Ready = ti.isSIM2Ready();//2번 장착
        boolean isDualsim = ti.isDualSIM();// 듀얼심 기종인지 체크
        
        if (isDualsim){
            if (isSIM1Ready&&isSIM2Ready){
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
                    SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
                    try {
                        List<SubscriptionInfo> subsInfoList = subscriptionManager.getActiveSubscriptionInfoList();
                        for (SubscriptionInfo subscriptionInfo : subsInfoList) {
                            number = subscriptionInfo.getNumber();
                        }
                    }
                    catch (SecurityException se){
                        return number;
                    }

                }
            }
        }

        return number;
    }

    /*
    * 번호가 더블
    * */
    public static List<String> getDualSimNumberList(Context context){
        List<String> lst = null;
        TelephonyInfo ti =TelephonyInfo.getInstance(context);

        boolean isSIM1Ready = ti.isSIM1Ready();//1번 장착
        boolean isSIM2Ready = ti.isSIM2Ready();//2번 장착
        boolean isDualsim = ti.isDualSIM();// 듀얼심 기종인지 체크


        if (isDualsim){
            if (isSIM1Ready&&isSIM2Ready){
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
                    SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
                    try {
                        List<SubscriptionInfo> subsInfoList = subscriptionManager.getActiveSubscriptionInfoList();
                        for (SubscriptionInfo subscriptionInfo : subsInfoList) {
                            lst.add(subscriptionInfo.getNumber());
                        }
                    }
                    catch (SecurityException se){
                        return lst;
                    }

                }
            }
        }

        return lst;
    }
}

사용

if (TelephonyInfo.getDualSimNumber(MainActivity.this) !=null){
	String phoneNumber = TelephonyInfo.getDualSimNumber(MainActivity.this);
}
반응형
반응형

permission 물어보기위한 공통 사항

  public static final String[] permissionList = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_PHONE_STATE};

    public static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 200;

- Common이라는 class안에 저장해서 쓰고있습니다. 아래도 자주 등장하니 참고해 주세요

- permissionList에 원하는 퍼미션을 넣어서 사용하면 됩니다.

permission 물어보기

        if (PermissionUtil.haveAllpermission(IntroActivity.this,Common.permissionList)){
            // 모든 퍼미션 허용
        }
        else{
           // 퍼미션 하나로도 허용 안함
           ActivityCompat.requestPermissions(mactivity,Common.permissionList,Common.MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
        }

- PermissionUtil에 haveAllpermission 펑션을 이용해 체크한다.

permission 결과 받기 -> onRequestPermissionsResult

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {


        //region 요청 코드가 PERMISSIONS_REQUEST_CODE 이고,
        // 요청한 퍼미션 개수만큼 수신되었다면
        if ( requestCode == Common.MY_PERMISSIONS_REQUEST_READ_PHONE_STATE && 
        		grantResults.length == Common.permissionList.length) {
                
            boolean check_result = true;

            // 모든 퍼미션을 허용했는지 체크합니다.
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    check_result = false;
                    break;
                }
            }

            //허용
            if ( check_result ) {
				//허용했을때 로직
            }
            //거부 ,재거부
            else {
                if (PermissionUtil.recheckPermission(this,Common.permissionList)){
                   //거부 눌렀을 때 로직
                }
                else{
                   //재거부 눌렀을 때 로직
                }
            }
        }
        //end region
    }

- onRequestPermissionsResult에서 결과를 받아 허용,거부,재거부일때 진행되는 로직을 설정해줍니다. 여기까지 하시면 몇가지가 안될것입니다.

 

-PermissionUtil class가 없는데 이제 만들러 가봅시다.

 

permission Util 만들기

public class PermissionUtil {


    /*
     * true : all permission granted
     * false : some permission deni
     * */
    public static boolean haveAllpermission(Context c , String[] s){
        boolean ispms = true;
        for (String pms : s ){
            if (ContextCompat.checkSelfPermission(c, pms) != PackageManager.PERMISSION_GRANTED  ) {
                ispms = false;
                break;
            }
        }
        return ispms;
    }

    /*
    * true : 사용자가 거부만 선택한 경우에는 앱을 다시 실행하여 허용을 선택하면 앱을 사용할 수 있습니다.
    * false : “다시 묻지 않음”을 사용자가 체크하고 거부를 선택한 경우에는 설정(앱 정보)에서 퍼미션을 허용해야 앱을 사용할 수 있습니다.
    * */
    public static boolean recheckPermission (Activity activity ,String[] permissions){
        boolean isrpms = false;
        for (String s : permissions){
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, s)){
                isrpms = true;
                break;
            }
        }
        return isrpms;
    }


}

- haveAllPermission은 모든 퍼미션들이 허용상태일땐 true를 아닐경우 false를 반환합니다.

- recheckPermission은 거부만 눌럿을때 true, 재거부를 눌럿을때 false를 반환합니다.

- 만들고보니 메소드 이름이 이상해서 바꾸실분들은 바꿔주세요 .. ㅋㅋㅋ

반응형

+ Recent posts