How to Set Mac Icon for Exported App

Your app comes through with the red icon; I’m not sure what else you want? What do you mean by ‘replace the one that processing is using’? The only time I ever see the default icon is on the dock when the app is opened.

I’m using Sonoma 14.5 (recent update) and it looks like they have deleted the ‘open anyway’ option. Usually if they take something away they give the user another option, but at this point I’m not sure what that is.

Addendum:
I finally got your app to open, but I’m sure that your clients aren’t going to want to go through the process. Basically I tried to run it through Terminal and it denied permission initially. I changed my permissions with chmod 755 and tried again and this time it worked. I also got a bunch of errors which I will share with you privately.

AppIcon:
This is the appearance of the downloaded app; it has your red icon.
exportIcon

When I try to open your app by double clicking on the icon (after changing the permissions) this is what I see (looks like an infinite loop, lots of beachballing)

The good news is that it has your custom icon on the dock as we would expect:
dock

Thank you.

I already have code in the sketch that creates the dock icon - this is not new. And it opens the same here, to the endless loading window and blank sketch.

You are seeing exactly the same thing I am.

The working app opens the main window. The exported app on my computer works fine.

The exported app sent you you - same file - does not. That’s the problem.

I really appreciate all your help.

I’m looking at the log you sent but so far all the messages are normal, except for these two:

Sound library warning: Did not find any sound devices with input channels, you won’t be able to use the AudioIn class

WARNING: Secure coding is not enabled for restorable state! Enable secure coding by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState: and returning YES.

Do you have any thoughts?

Also, how did you get the error log?

Thank you so much Svan. I do appreciate it.

I see this warning in many apps on both platforms Linux and Mac. It is easily fixed by adding that method to the AppDelegate. You don’t have access to the objc AppDelegate so I’m afraid that you won’t be able to fix it. However, the authors of the Processing editor could probably fix it as they create the app bundle. It is a harmless warning at this point.

The error log comes from Terminals menu Shell/Export Text As…

I already have code in the sketch that creates the dock icon
How does that work? What’s the source code or procedure?

Addendum:
And it opens the same here, to the endless loading window and blank sketch.

Go into the app bundle and double click on the executable file in the MacOS folder and it opens right up.

Addendum_2:
I downloaded your app a second time and opened the bundle when it failed to launch. Here’s what your executable (MacOS folder in app bundle) looks like:
exe_orig

No wonder it doesn’t launch. It’s supposed to look like this:
exe

Thank you Svan for your time. I do not take it, or you, for granted :smiling_face_with_three_hearts:

I’ll look into the Terminals shell. So did you launch the app from the Terminal then?

But none of the errors explain the blank screen.

The app is supposed to launch and look like this:

Are you saying that it did launch to this screen for you? Because it never has on the shared executable.

For the dock icon, I used this:

appIcon = loadImage("appIcon.png");
surface.setIcon(appIcon);

(And I put the appIcon.png in the data folder.)

Go into the app bundle and double click on the executable file in the MacOS folder and it opens right up.

The originally exported app does open right up - no need to do anything but double click the main icon.

For the version that is sent over the internet, it does not open right up, unless you change the permissions. And then, it opens to the blank page you experienced.

I simply cannot get this to work right once it’s been sent out. But the same exact exported app folder and executable work flawlessly here until I send it to someone.

So yes, I still thing something is happening to the exported app when it’s being sent to another person, because it WORKS on my computer, and if I send it to myself using WeTransfer it doesn’t work anymore. I did read somewhere that Apple adds some tags or something, but I’m not sure how that’s even possible.

No wonder it doesn’t launch. It’s supposed to look like this:

Before sending it out, it DOES have that exec icon! But it gets changed when sent using a file transfer.

I so appreciate your time Svan. I’m feeling frustrated because I’m no closer to fixing any of the three issues:

  1. The app not opening at all (and giving the “Application can’t be opened” error)
  2. After fixing permissions, opening to a blank screen, and,
  3. Changing the main icon. It never did work using custom application.icns file, despite being listed in the Plist

Do you, or anyone reading this thread, have any ideas how to troubleshoot and solve these problems?

I feel like a lot of this is the kind of behind-the-scenes stuff that Processing should do for the export feature. Why bother giving an export app function if the resultant file does not work when you share it? Authors have little need for an exported app; the main reason to export an app is to share it.

And it simply isn’t working.

Do any processing.org programmers monitor these threads? Maybe I need to reopen or raise this issue again at their gitHub

Thank you so much,

Mike

Things aren’t consistent and make little sense; I agree that there are serious problems. I did get the app to launch (looked like your posted image) on the first download when I double clicked on the bundle executable (after changing the permissions). However, I was unable to duplicate that success with the second download. The executable icon changed from a text looking icon to a normal looking executable icon after changing the permissions in Terminal but it still wouldn’t launch. I also noticed that the options.txt file was missing from the second download. Judging by all the files in your data folder it looks like a pretty complicated app. You might want to try to build it in some other editor. I would have liked to have been more help, but there are things beyond my control also. I can tell that you have spent a lot of time and energy on this app and wish you good luck on finishing it. Don’t give up.

One last thought: can you send a standard .zip file (right click on a workable app file, select Compress"xxxx"). I’m not familiar with your transfer app. Github is another possibility if you don’t do dropbox. This may not change anything, but it won’t hurt to try.

1 Like

Thank you Svan.

Again, so many thanks for your expertise, encouragement, and your time :star_struck:

I did manage to get the icon issue sorted out - apparently I didn’t have the command line tools installed for Xcode, and now the app icons show correctly.

But still it won’t open even with those tools installed. I still have to reset the permissions. I will try other suggestions I saw in the export wiki.

Also, the options and presets folder are missing on purpose (or should be), because they are built on first open of the app. The options contain a reference to their own location, so I don’t want to send out the app with the file path listed as it will be wrong if I do, but it will be right if the app builds it.

Thank you again. I will probably continue to post to this thread, but I don’t expect you to keep responding. You’ve done over and above the call of duty!

You’ve been absolutely amazing :smiling_face_with_three_hearts: Thank you so, so much.

Mike

Svan! I’ve got it working!!!

I did all three of the export wiki suggestions, and after doing all three, PLUS changing the permissions, the file works and opens correctly!!!

Is there any chance I can send you the file and have you try it one more time for me, as independent verification?

If not, no worries; as I said, you’ve put in your time!! And I’m so grateful to you for it!

Thanks,

Mike

Certainly you can send the file; I’m anxious to see it. Thanks and congratulations.

You said you did all three things: did you get an Apple developer account too?

Addendum:
I told you that my second download failed after I changed the permissions. I went back and took that same app out of quarantine and now the app launches when I double click on the app bundle executable in the MacOS folder. It could also be run from the command line. That matches with your findings: You have to 1) change the permissions and 2) take it out of quarantine. Having said that I’m not sure you should have to do all of that just to share your exported app. Here is what I saw when I double clicked the app’s main executable (looks like a tv screen after changing the permissions; looked like a text file icon when I first got it). Furthermore, the app itself then opened when its icon was double clicked. However, I was unable to reproduce this with other downloads which just showed the beachballing gray screen and not the main app when their app icon was double clicked.

Thank you Svan!

I will send tomorrow (it’s 4am here!).

No I did not get a dev account, but I did install the x-code command line tools - which I mistakenly thought I already had since I have XCode - and also tried the other two command line items.

Apparently it’s the combo of the command line tools and changing permissions on the exe file and the third command line item that made it work. No need for the quarantine line (on my computer anyway).

And the icons are working now too, bonus!

I’ll send tomorrow, and thank you again!

Mike

Apparently it’s the combo of the command line tools and changing permissions on the exe file and the third command line item that made it work. No need for the quarantine line (on my computer anyway).

What’s the third command line item? Taking it out of quarantine was a co-factor on my M2 mac.

More observations:
I downloaded the exported Processing app that I sent to you onto my M2 mac (it was uploaded from an Intel mac) and it would not launch with an error message similar to your app. However, the app bundle executable file had the correct appearance unlike your app (looked like a tv set) and the app launched when I double clicked the executable file. However, initially the app would not launch when I double clicked the app icon. After taking it out of quarantine it then ran as expected. I did not have to change the permissions like you did, just take it out of quarantine. It appears that you do not have to change the permissions if the executable looks normal (not like a text file).

Addendum:
I received a second version of your app and unfortunately it behaves just like the first version and still will not launch correctly. I initially tried taking it out of quarantine and that alone still would not allow it to launch by double clicking the app icon. When I examined the app bundle, the executable file was malformed and looked like a text file icon. After I changed the permissions with chmod 755 it reverted to a normal looking executable (tv screen). Double clicking the bundle executable then launched the app (first image below). However after all of that it still won’t launch when the app icon is double clicked and only a beach balling gray screen is seen (second image shown below):
After removal from quarantine and changing permissions double click on bundle executable:

Double click on app icon:

Summary:
On this end nothing changed from previous experience. Perhaps try sending just a .zipped version of a runnable export version from your system. Were you ever able to ‘fix’ the app I sent to you? All that you should have to do to that one is remove the quarantine.

Thank you for your time Svan. I will look into what you shared.

I was up so late I think I missed the fact you had replied - apologies.

The app was output directly from Processing, so I’m not sure why the exe would be malformed.

I tried taking your app out of quarantine with this line:

xattr -d com.apple.quarantine (app path)

This works. Now I can open it normally. Prior to that it was saying the app was damaged. Strange message that didn’t conform to the actual issue.

I will try sending you a zipped version of the my app that runs on my system fine, and see what happens for you. Look in your email in a little bit.

Thx so much,

Mike

Just for your information the app below is what I use to take a mac app out of quarantine. I wrote it some time ago probably in objc, but you could do something similar in Processing; it uses drag 'n drop and will save you having to open Terminal and trying to remember the command.

Addendum:
I received your latest e-mail and whatever you did worked like a charm. I saw your app with its regular icon in my downloads folder and I pulled it out to my desktop and double clicked on it and it worked as expected. I’m not sure what you did, but it worked on my M2 system. Usually a .zip file has its icon shown below and you have to double click on it to unzip it, but your file came through without it.
zip

1 Like

OK! That is so interesting!

First - hats off on your app! Looks really cool. Is it available anywhere?

Secondly, it appears that first zipping the file preserves everything in a working state…

I will further test this, and you have given me a very valuable lead here Svan.

Truly, I can’t thank you enough for all your TIME and caring to share with a stranger. I hope I can help someone else out the same sometime.

Many, MANY thanks!!!

All the best,

Mike

The following source code is for a Processing app using Swing components to allow you to check for quarantine on a mac app. It will run on a mac M2 system, but has not been extensively tested. The command strings could be changed to meet your needs. Please be aware that folder names with spaces will cause it to fail.

import java.awt.*;
import javax.swing.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.util.List;
import javax.swing.TransferHandler;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.*;

JFrame frame;
Canvas canvas;
JTextField pathFld;
JTextField resultFld;
JTextField cmdFld;
JButton checkBtn;
JButton removeBtn;

int _wndW = 700;
int _wndH = 400;
String filePath = null;

void showErrorMessage() {
  String msgStr = "No file path. Please drag 'n drop a\n mac app to check for quarantine.";
  JOptionPane.showMessageDialog(frame, msgStr);
}

void checkForQuarantine() {
  Process proc;
  String cmd = "/usr/bin/xattr -p -l com.apple.quarantine " + filePath;
  if (filePath != null) {
    cmdFld.setText(cmd);
    try {
      proc = Runtime.getRuntime().exec(cmd);
      BufferedReader out = new BufferedReader(new InputStreamReader(proc.getInputStream()));
      BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
      String s = null;
      while ((s = out.readLine()) != null) {
        resultFld.setText(s);
      }
      while ((s = err.readLine()) != null) {
        resultFld.setText(s);
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  } else {
    showErrorMessage();
  }
}

void removeQuarantine() {
  Process proc;
  String cmd = "/usr/bin/xattr -r -d com.apple.quarantine " + filePath;
  if (filePath != null) {
    cmdFld.setText(cmd);
    try {
      proc = Runtime.getRuntime().exec(cmd);
      BufferedReader out = new BufferedReader(new InputStreamReader(proc.getInputStream()));
      BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
      String s = null;
      while ((s = out.readLine()) != null) {
        resultFld.setText(s);
      }
      while ((s = err.readLine()) != null) {
        resultFld.setText(s);
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  } else {
    showErrorMessage();
  }
}

void buildWnd() {
  checkBtn = new JButton("2. Check for quarantine");
  checkBtn.setBounds(20, 20, 180, 24);
  checkBtn.addActionListener(new ActionListener() {
    public void actionPerformed (ActionEvent e) {
      checkForQuarantine();
    }
  }
  );
  removeBtn = new JButton("3. Remove quarantine");
  removeBtn.setBounds(210, 20, 180, 24);
  removeBtn.addActionListener(new ActionListener() {
    public void actionPerformed (ActionEvent e) {
      removeQuarantine();
    }
  }
  );
  // bounds controlled by frame componentListener
  pathFld = new JTextField();
  cmdFld = new JTextField();
  resultFld = new JTextField();

  frame.add(checkBtn);
  frame.add(removeBtn);
  frame.add(pathFld);
  frame.add(cmdFld);
  frame.add(resultFld);
  frame.add(canvas);
  frame.setVisible(true);
}

void setup() {
  surface.setVisible(false);
  frame = new JFrame("1. Drag 'n drop mac app.");
  frame.setBounds(100, 100, _wndW, _wndH);
  frame.setLayout(null);
  canvas = new Canvas();
  // =========== Drag and Drop =========== //
  canvas.setDropTarget(new DropTarget(canvas, DnDConstants.ACTION_COPY_OR_MOVE, new DropTargetListener() {
    @Override
      public void dragEnter(DropTargetDragEvent dtde) {
    }
    @Override
      public void dragOver(DropTargetDragEvent dtde) {
    }
    @Override
      public void dropActionChanged(DropTargetDragEvent dtde) {
    }
    @Override
      public void dragExit(DropTargetEvent dte) {
    }
    @Override
      public void drop(DropTargetDropEvent evt) {
      // Accept copy drops
      evt.acceptDrop(DnDConstants.ACTION_COPY);
      // Get the transfer to provide dropped item data
      Transferable transferable = evt.getTransferable();
      // Get the data formats of dropped item
      DataFlavor[] flavors = transferable.getTransferDataFlavors();
      // Loop through the flavors
      for (DataFlavor flavor : flavors) {
        try {
          // If the drop items are files
          if (flavor.isFlavorJavaFileListType()) {
            // Get all of the dropped files
            List<File> files = new ArrayList<>();
            files = (List)transferable.getTransferData(flavor);
            // Loop them through
            for (File file : files) {
              filePath = file.getPath();
              pathFld.setText(filePath);
            }
          }
        }
        catch (Exception e) {
          e.printStackTrace();   // Print out the error stack
        }
      }
      evt.dropComplete(true);  // Inform that the drop is complete
    }
  }
  ));

  frame.addComponentListener(new java.awt.event.ComponentAdapter() {
    public void componentResized(ComponentEvent e) {
      JFrame tmp = (JFrame)e.getSource();
      canvas.setBounds(0, 0, tmp.getWidth(), tmp.getHeight());
      pathFld.setBounds(20, 50, tmp.getWidth() - 40, 30);
      cmdFld.setBounds(20, 80, tmp.getWidth() - 40, 30);
      resultFld.setBounds(20, 110, tmp.getWidth() - 40, 30);
    }
  }
  );

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      buildWnd(); // Builds components on EventDispatchThread
    }
  }
  );
}

Output:

1 Like

Svan! I never thanked you for this! Apologies!

I will check it out. Thank you for being so generous with your hard won code!!

Mike