2010-02-07 29 views
12

Thời gian chạy không khí Adobe ngăn không cho nhiều ứng dụng không khí được khởi động cùng một lúc. Có an toàn để vượt qua hạn chế này bằng cách tùy ý thay đổi ID nhà xuất bản không? Có ai biết nếu Adobe có kế hoạch cho phép nhiều trường hợp đồng thời trong Air 2.0?bắt đầu một ứng dụng Adobe AIR nhiều lần

+0

câu trả lời tốt đẹp lòng để kiếm được tiền thưởng. – abc

Trả lời

19

Chúng tôi đã triển khai thành công một bản hack để vượt qua giới hạn này, theo cách AIR thuần túy mà không phải thay đổi id nhà xuất bản (cần nhiều chứng chỉ).

Như bạn đã biết, AIR đang triển khai Mutex bằng cách sử dụng số nhận dạng ứng dụng duy nhất. Số nhận dạng này được tính bằng cách sử dụng id ứng dụng và số nhận dạng nhà xuất bản (được trích xuất từ ​​chứng chỉ đã ký ứng dụng).

Trong thư mục cài đặt của ứng dụng AIR, có thư mục META-INF (hoặc trong/share/using Linux). Thư mục META-INF này chứa một thư mục AIR, chứa một tệp "application.xml". Tệp này chứa thẻ <id /> xác định số nhận dạng ứng dụng, được sử dụng để tính toán số nhận dạng mutex. Nếu ứng dụng của bạn có thể viết trong thư mục cài đặt, bạn có thể sử dụng API File để chỉnh sửa nó trong thời gian chạy, thay đổi ngẫu nhiên thẻ <id />, cho phép nhiều quy trình của cùng một ứng dụng được chạy cùng một lúc.

Đây là một số tác dụng phụ gây phiền nhiễu, chẳng hạn như tạo thư mục mới trong thư mục File.applicationStorageDirectory mỗi lần. Nhưng bằng cách sử dụng một LocalConnection, bạn có thể giảm thiểu điều này bằng cách sử dụng lại cùng một số nhận dạng nhiều lần bằng cách đăng nhập cái nào là miễn phí để được sử dụng lại. Ngoài ra, SharedObject được lưu trữ trong thư mục này, vì vậy không thể được sử dụng (hoặc phải được sao chép mỗi khi một cá thể mới được tạo và đồng bộ hóa mặc dù LocalConnection).

Theo như tôi biết, Adobe không định loại bỏ giới hạn gốc này. Nó được thực hiện cho các mục đích đa nền tảng, đặc biệt trên MacOS, nơi mà dock làm cho nó phức tạp hơn (nó không phải là rất dễ dàng để bắt đầu cùng một ứng dụng hai lần với dock).

Cách chính thức để làm điều đó là bắt sự kiện InvokeEvent.INVOKE và thực hiện các công việc như mở cửa sổ mới. Và không có thay đổi nào được lên kế hoạch cho AIR 2.0 trong hành vi này.

1

Sẽ giúp ích nếu bạn đóng gói logic ứng dụng của mình dưới dạng lớp có thể chạy trong cửa sổ và cho phép người dùng tạo nhiều phiên bản của cửa sổ đó, trong một ứng dụng? điều đó có giúp ích gì không?

Lý do chính khiến bạn cần nhiều ứng dụng là gì?

+0

Cảm ơn câu trả lời, nhưng tôi đặc biệt tìm kiếm các quy trình riêng biệt. Có một số lợi ích, ví dụ như thực hiện song song trên các máy tính đa xử lý. – abc

+0

Tôi hiểu, cảm ơn lời giải thích. Câu hỏi hay. Bạn có thể có các quá trình riêng biệt trong Java ... điều này có thể là cách để dài quanh co, sẽ giao tiếp AIR và Java thông qua Merapi (http://merapiproject.net/) làm bất kỳ tốt? –

+0

Một lần nữa, bài viết thú vị, nhưng nó là tắt chủ đề. Merapi là một khuôn khổ IPC chứ không phải là một khung liên kết (chẳng hạn như JNI), do đó, nó không thể liên kết với một thư viện java đa luồng; sẽ phải có một quá trình java bắt đầu riêng. Hơn nữa, bằng cách sử dụng một trình trợ giúp java sẽ chỉ cung cấp xử lý song song, không phải lợi thế khác của nhiều quy trình. Hãy quay trở lại câu hỏi ban đầu: Tôi đang tìm cách để bắt đầu một số trường hợp của một ứng dụng Flex AIR, và đặc biệt cho dù chạy cùng một swf với nhiều ID nhà xuất bản là hợp pháp trong thời gian chạy AIR. – abc

0

Thao tác này sẽ tự động cập nhật, được cảnh báo.

1

Ứng dụng sao chép không khí sẽ giúp bạn trong phần này. Sử dụng điều này bạn có thể chạy nhiều trường hợp của cùng một ứng dụng AIR.

https://github.com/chrisdeely/AirAppDuplicator

của nó chỉ đơn giản là sao chép thư mục ứng dụng của bạn với tên mới và id ứng dụng mới.

0

Chỉ cần thực hiện một lớp học nhanh để triển khai giải pháp của Tyn. Đơn giản chỉ cần gọi. MultipleInstanceAirApp.changeMetaInfId(stage);

Bạn không thực sự cần phần sân khấu, nhưng tôi sử dụng nó để thay đổi vị trí của cửa sổ khi tôi kiểm tra. Dù sao, hãy tận hưởng!

import flash.display.Stage; 
import flash.events.Event; 
import flash.events.IOErrorEvent; 
import flash.filesystem.File; 
import flash.filesystem.FileMode; 
import flash.filesystem.FileStream; 
import flash.utils.ByteArray; 

/** 
* @author Lachhh 
*/ 
public class MultipleInstanceAirApp { 
    static private var loadFile : File; 
    static private var thePath:String = "./META-INF/AIR/application.xml"; 
    static private var myGameId:String = "YOUR_GAME_ID"; 
    static private var stage:Stage ; 
    static private var metaInfString:String ; 

    static public var instanceNumber:int = 0; 

    static public function changeMetaInfId(pStage:Stage):void { 
     stage = pStage; 
     var path:String = File.applicationDirectory.resolvePath(thePath).nativePath; 
     loadFile = new File(path); 

     loadFile.addEventListener(Event.COMPLETE, onLoadMetaInf); 
     loadFile.addEventListener(IOErrorEvent.IO_ERROR, onIoError); 
     loadFile.load(); 
    } 

    private static function onLoadMetaInf(event : Event) : void { 
     loadFile.removeEventListener(Event.COMPLETE, onLoadMetaInf); 
     metaInfString = loadFile.data.toString(); 
     replaceMetaInfIdIfFound(); 
     saveStringToMetaInf(metaInfString); 
    } 

    static public function saveStringToMetaInf(s:String):void { 
     var b:ByteArray = new ByteArray(); 
     b.writeUTFBytes(s); 
     saveFile(b); 
    } 

    static public function saveFile(data:ByteArray):void { 
     var thePath:String = File.applicationDirectory.resolvePath(thePath).nativePath;  
     var saveFile:File = new File(thePath); 
     var fileStream:FileStream = new FileStream(); 
     fileStream.openAsync(saveFile, FileMode.WRITE); 
     fileStream.writeBytes(data); 
     fileStream.addEventListener(Event.CLOSE, onClose); 
     fileStream.close(); 
    } 

    static private function replaceMetaInfIdIfFound():void { 
     if(checkToReplaceId(1, 2)) return ; 
     if(checkToReplaceId(2, 3)) return ; 
     if(checkToReplaceId(3, 4)) return ; 
     checkToReplaceId(4, 1); 

    } 

    static private function checkToReplaceId(i:int, newI:int):Boolean { 
     var id:String = getGameIdWithBrackets(i); 
     var newId:String = getGameIdWithBrackets(newI); 
     if(metaInfString.indexOf(id) != -1) { 
      metaInfString = myReplace(metaInfString, id, newId); 
      instanceNumber = newI; 
      return true; 
     } 
     return false; 
    } 

    private static function onClose(event : Event) : void { 
     trace("all done!"); 
     placeScreenAccordingToInstanceNumber(); 
    } 

    static private function placeScreenAccordingToInstanceNumber():void {; 
     switch(instanceNumber) { 
      case 1 : 
       stage.nativeWindow.x = 115; 
       stage.nativeWindow.y = 37; 
       break; 
      case 2 : 
       stage.nativeWindow.x = 115 + 660; 
       stage.nativeWindow.y = 37; 
       break; 
      case 3 : 
       stage.nativeWindow.x = 115; 
       stage.nativeWindow.y = 37 + 380; 
       break; 
      case 4 : 
       stage.nativeWindow.x = 115 + 660; 
       stage.nativeWindow.y = 37 + 380; 
       break; 
     } 
    } 

    private static function onIoError(event : IOErrorEvent) : void { 
     trace("io Error"); 
    } 

    static private function getGameIdOriginalWithBrackets():String { 
     return "<id>" + myGameId + "</id>"; 
    } 

    static private function getGameIdWithBrackets(i:int):String { 
     if(i == 1) return getGameIdOriginalWithBrackets(); 
     return "<id>" + myGameId + i + "</id>"; 
    } 

    static public function myReplace(msg:String, toFind:String, toBeReplacedWith:String):String { 
     return msg.split(toFind).join(toBeReplacedWith) ; 
    } 
} 
0
package hobis.airpc 
{ 
    import flash.events.Event; 
    import flash.filesystem.File; 
    import flash.filesystem.FileMode; 
    import flash.filesystem.FileStream; 
    import flash.utils.ByteArray; 
    import jhb0b.utils.MArrayUtil; 

    public final class MAppXmlUpdateCounter 
    { 
     private static var _AppXmlFile:File; 

     public static function Update():void 
     { 
      _AppXmlFile = new File(File.applicationDirectory.nativePath);   
      _AppXmlFile = _AppXmlFile.resolvePath('META-INF\\AIR\\application.xml'); 
      _AppXmlFile.addEventListener(Event.COMPLETE, ppOpened); 
      _AppXmlFile.load();   
     } 

     private static function ppOpened(evt:Event):void 
     { 
      const trx1:RegExp = /<id>[\s\S]*?<\/id>/; 
      const trx2:RegExp = /<([^>]+)>/g; 

      var tXmlStr:String = _AppXmlFile.data.toString(); 
      var tMatArr:Array = tXmlStr.match(trx1); 
      if (!MArrayUtil.is_empty(tMatArr)) 
      { 
       var tIdTagStr:String = tMatArr[0]; 
       var tIdValStr:String = tIdTagStr.replace(trx2, ''); 

       var tOriVal:String; 
       var tNumVal:uint; 
       var tStrArr:Array = tIdValStr.split('-'); 
       if (tStrArr != null) 
       { 
        if (tStrArr.length == 2) 
        { 
         tOriVal = tStrArr[0]; 
         tNumVal = int(tStrArr[1]);        
        } 
        else 
        if (tStrArr.length == 1) 
        { 
         tOriVal = tStrArr[0]; 
         tNumVal = 0; 
        } 
        tNumVal++; 

        var tIdNewStr:String = '<id>' + tOriVal + '-' + tNumVal + '<\/id>';     
        var tNewXmlStr:String = tXmlStr.replace(tIdTagStr, tIdNewStr);     
        ppSaveFile(tNewXmlStr); 
       } 
      } 
      _AppXmlFile = null; 
     } 

     private static function ppSaveFile(val:String):void 
     { 
      var tfs:FileStream; 
      try 
      { 
       tfs = new FileStream(); 
       tfs.openAsync(_AppXmlFile, FileMode.WRITE); 
       var tba:ByteArray = new ByteArray(); 
       tba.writeUTFBytes(val);   
       tfs.writeBytes(tba);     
       tba.clear(); 
      } 
      catch (e:Error) { } 
      try 
      { 
       tfs.close(); 
      } 
      catch (e:Error) { } 
     } 
    } 
} 
+0

Chào mừng bạn đến với Stack Overflow! Trong khi đoạn mã này được chào đón, và có thể cung cấp một số trợ giúp, nó sẽ được [cải thiện rất nhiều nếu nó bao gồm một lời giải thích] (// meta.stackexchange.com/q/114762) của * how * nó giải quyết các câu hỏi. Nếu không có điều đó, câu trả lời của bạn có giá trị giáo dục ít hơn nhiều - hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ là người hỏi bây giờ! Vui lòng [sửa] câu trả lời của bạn để thêm giải thích và đưa ra chỉ dẫn về những giới hạn và giả định được áp dụng. –

Các vấn đề liên quan